#include <bits/stdc++.h>
using namespace std;

class Node
{
public:
    int value;
    Node *next;
    Node *prev;

    Node(int value)
    {
        this->value = value;
        next = prev = NULL;
    }
};

class DLL
{
private:
    int length;
    Node *head;
    Node *tail;

public:
    DLL(int value)
    {
        Node *newNode = new Node(value);
        tail = head = newNode;
        length = 1;
    }

    // printlist
    void printList()
    {
        Node *temp = head;
        while (temp != NULL)
        {
            cout << temp->value << " -> ";
            temp = temp->next;
        }
        cout << "NULL" << endl;
    }

    // append
    void append(int value)
    {
        Node *newNode = new Node(value);
        if (head == NULL)
        {
            head = tail = newNode;
        }
        else
        {
            tail->next = newNode;
            newNode->prev = tail;
            tail = newNode;
        }
        length++;
        return;
    }

    // delete last
    void deleteLast()
    {
        if (head == NULL)
        {
            cout << "invalid operation on empty list" << endl;
            return;
        }

        if (head->next == NULL)
        {
            delete head;
            head = tail = NULL;
            length--;
            return;
        }

        Node *temp = tail;
        tail = tail->prev;
        tail->next = NULL;
        delete temp;
        length--;
        return;
    }

    // prepend
    void prepend(int value)
    {
        Node *newNode = new Node(value);
        if (head == NULL)
        {
            head = tail = newNode;
        }
        else
        {
            newNode->next = head;
            head->prev = newNode;
            head = newNode;
        }
        length++;
        return;
    }

    // delete first
    void deleteFirst()
    {
        if (head == NULL)
        {
            cout << "invalid operation on empty list" << endl;
            return;
        }

        if (head->next == NULL)
        {
            delete head;
            head = NULL;
            tail = NULL;
        }
        else
        {
            Node *temp = head;
            head = head->next;
            head->prev = NULL;
            delete temp;
        }
        length--;
        return;
    }

    Node *get(int index)
    {
        if (index < 0 || index >= length)
        {
            cout << "invalid index" << endl;
            return NULL;
        }

        Node *temp = head;
        if (index < length / 2)
        {
            for (int i = 0; i < index; i++)
            {
                temp = temp->next;
            }
        }
        else
        {
            temp = tail;
            for (int i = length - 1; i > index; i++)
            {
                temp = temp->prev;
            }
        }
        return temp;
    }

    bool set(int index, int value){
        Node* temp = get(index);
        if(temp != NULL){
            temp->value = value;
            return true;
        }
        return false;
    }

};

int main(){
    DLL *d1 = new DLL(0);
    d1->append(1);
    d1->append(2);
    d1->append(3);
    d1->set(0,100);
    d1->printList();
}


//*****************************************//
//  sysextest.cpp
//  by Gary Scavone, 2003-2005.
//
//  Simple program to test MIDI sysex sending and receiving.
//
//*****************************************//

#include <iostream>
#include <cstdlib>
#include <typeinfo>
#include "RtMidi.h"

void usage( void ) {
  std::cout << "\nuseage: sysextest N\n";
  std::cout << "    where N = length of sysex data to send / receive.\n\n";
  exit( 0 );
}

// Platform-dependent sleep routines.
#if defined(_WIN32)
  #include <windows.h>
  #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds )
#else // Unix variants
  #include <unistd.h>
  #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )
#endif

// This function should be embedded in a try/catch block in case of
// an exception.  It offers the user a choice of MIDI ports to open.
// It returns false if there are no ports available.
bool chooseMidiPort( RtMidi *rtmidi );

RtMidi::Api chooseMidiApi();

void mycallback( double deltatime, std::vector< unsigned char > *message, void * /*userData*/ )
{
  unsigned int nBytes = message->size();
  for ( unsigned int i=0; i<nBytes; i++ )
    std::cout << "Byte " << i << " = " << (int)message->at(i) << ", ";
  if ( nBytes > 0 )
    std::cout << "# of bytes = " << nBytes << ", stamp = " << deltatime << std::endl;
}

int main( int argc, char *argv[] )
{
  RtMidiOut *midiout = 0;
  RtMidiIn *midiin = 0;
  std::vector<unsigned char> message;
  unsigned int i, nBytes;

  // Minimal command-line check.
  if ( argc != 2 ) usage();
  nBytes = (unsigned int) atoi( argv[1] );

  // RtMidiOut and RtMidiIn constructors
  try {
    RtMidi::Api api = chooseMidiApi();
    midiout = new RtMidiOut( api );
    midiin = new RtMidiIn( api );
  }
  catch ( RtMidiError &error ) {
    error.printMessage();
    goto cleanup;
  }

  // Don't ignore sysex, timing, or active sensing messages.
  midiin->ignoreTypes( false, true, true );

  try {
    if ( chooseMidiPort( midiin ) == false ) goto cleanup;
    if ( chooseMidiPort( midiout ) == false ) goto cleanup;

    midiin->setCallback( &mycallback );

    message.push_back( 0xF6 );
    midiout->sendMessage( &message );
    SLEEP( 500 ); // pause a little

    // Create a long sysex message of numbered bytes and send it out ... twice.
    for ( int n=0; n<2; n++ ) {
      message.clear();
      message.push_back( 240 );
      for ( i=0; i<nBytes; i++ )
        message.push_back( i % 128 );
      message.push_back( 247 );
      midiout->sendMessage( &message );

      SLEEP( 500 ); // pause a little
    }
  }
  catch ( RtMidiError &error ) {
    error.printMessage();
    goto cleanup;
  }

  // Clean up
 cleanup:
  delete midiout;
  delete midiin;

  return 0;
}

bool chooseMidiPort( RtMidi *rtmidi )
{
  bool isInput = false;
  if ( typeid( *rtmidi ) == typeid( RtMidiIn ) )
    isInput = true;

  if ( isInput )
    std::cout << "\nWould you like to open a virtual input port? [y/N] ";
  else
    std::cout << "\nWould you like to open a virtual output port? [y/N] ";

  std::string keyHit;
  std::getline( std::cin, keyHit );
  if ( keyHit == "y" ) {
    rtmidi->openVirtualPort();
    return true;
  }

  std::string portName;
  unsigned int i = 0, nPorts = rtmidi->getPortCount();
  if ( nPorts == 0 ) {
    if ( isInput )
      std::cout << "No input ports available!" << std::endl;
    else
      std::cout << "No output ports available!" << std::endl;
    return false;
  }

  if ( nPorts == 1 ) {
    std::cout << "\nOpening " << rtmidi->getPortName() << std::endl;
  }
  else {
    for ( i=0; i<nPorts; i++ ) {
      portName = rtmidi->getPortName(i);
      if ( isInput )
        std::cout << "  Input port #" << i << ": " << portName << '\n';
      else
        std::cout << "  Output port #" << i << ": " << portName << '\n';
    }

    do {
      std::cout << "\nChoose a port number: ";
      std::cin >> i;
    } while ( i >= nPorts );
    std::getline(std::cin, keyHit);  // used to clear out stdin
  }

  std::cout << std::endl;
  rtmidi->openPort( i );

  return true;
}

RtMidi::Api chooseMidiApi()
{
  std::vector< RtMidi::Api > apis;
  RtMidi::getCompiledApi(apis);

  if (apis.size() <= 1)
    return RtMidi::Api::UNSPECIFIED;

  std::cout << "\nAPIs\n  API #0: unspecified / default\n";
  for (size_t n = 0; n < apis.size(); n++)
    std::cout << "  API #" << apis[n] << ": " << RtMidi::getApiDisplayName(apis[n]) << "\n";

  std::cout << "\nChoose an API number: ";
  unsigned int i;
  std::cin >> i;

  std::string dummy;
  std::getline(std::cin, dummy);  // used to clear out stdin

  return static_cast<RtMidi::Api>(i);
}


#include <string>
#include <ros/ros.h>
#include <serial/serial.h>
#include <std_msgs/String.h>
#include <std_msgs/Empty.h>
#include <std_msgs/UInt16.h>
#include <std_msgs/Float32.h>
#include <std_msgs/Bool.h>
#include <sensor_msgs/JointState.h>
#include <geometry_msgs/Pose.h>
#include <math.h>
#include <unistd.h>
#include <tf/transform_datatypes.h>

serial::Serial _serial;				// serial object
bool HomingComplete = false;
bool CommandComplete = false;
bool MoveComplete = false;
bool GripperComplete = false;
bool ArmMoveComplete = false;
bool CanMove = false;
bool GrabStart = false;

//pick and place?
void grab_write_callback(const std_msgs::Bool msg)
{
	std::string Gcode = "";

	if(msg.data==true) GrabStart = true;
	else
	{
		Gcode = (std::string)"M21 G90 G01 X0.00 Y38.90 Z21.30 A0.00 B-60.30 C0.00 F2000.00" + "\r\n";
		_serial.write(Gcode.c_str());
		while (ros::ok())
		{
			Gcode = (std::string)"?" + "\r\n";
			_serial.write(Gcode.c_str());
			ros::Duration(0.1).sleep();
			std_msgs::String result;
			result.data = _serial.read(_serial.available());
			ArmMoveComplete = (result.data.npos == result.data.find("Idle"))?false:true;
			if(ArmMoveComplete == true)break;
		}
		ros::Duration(1).sleep();

		Gcode = (std::string)"M21 G90 G01 X0.00 Y48.00 Z17.30 A0.00 B-65.30 C0.00 F2000.00" + "\r\n";
		_serial.write(Gcode.c_str());
		while (ros::ok())
		{
			Gcode = (std::string)"?" + "\r\n";
			_serial.write(Gcode.c_str());
			ros::Duration(0.1).sleep();
			std_msgs::String result;
			result.data = _serial.read(_serial.available());
			ArmMoveComplete = (result.data.npos == result.data.find("Idle"))?false:true;
			if(ArmMoveComplete == true)break;
		}
		ros::Duration(1).sleep();

		Gcode = (std::string)"M3S60" + "\r\n";
                _serial.write(Gcode.c_str());
                while (ros::ok())
                {
                        ros::Duration(0.1).sleep();
                        std_msgs::String result;
                        result.data = _serial.read(_serial.available());
                        GripperComplete = (result.data.npos == result.data.find("ok"))?false:true;
                        if(GripperComplete == true)break;
                }
                ros::Duration(1).sleep();

		Gcode = (std::string)"M21 G90 G01 X0.00 Y38.90 Z21.30 A0.00 B-60.30 C0.00 F2000.00" + "\r\n";
                _serial.write(Gcode.c_str());
                while (ros::ok())
                {
                        Gcode = (std::string)"?" + "\r\n";
                        _serial.write(Gcode.c_str());
                        ros::Duration(0.1).sleep();
                        std_msgs::String result;
                        result.data = _serial.read(_serial.available());
                        ArmMoveComplete = (result.data.npos == result.data.find("Idle"))?false:true;
                        if(ArmMoveComplete == true)break;
                }
                ros::Duration(1).sleep();

		Gcode = (std::string)"M21 G90 G01 X90.00 Y-40.00 Z40.00 A0.00 B0.00 C0.00 F2000.00" + "\r\n";
                _serial.write(Gcode.c_str());
                while (ros::ok())
                {
                        Gcode = (std::string)"?" + "\r\n";
                        _serial.write(Gcode.c_str());
                        ros::Duration(0.1).sleep();
                        std_msgs::String result;
                        result.data = _serial.read(_serial.available());
                        ArmMoveComplete = (result.data.npos == result.data.find("Idle"))?false:true;
                        if(ArmMoveComplete == true)break;
                }
                ros::Duration(1).sleep();

		Gcode = (std::string)"M3S40" + "\r\n";
                _serial.write(Gcode.c_str());
                while (ros::ok())
                {
                        ros::Duration(0.1).sleep();
                        std_msgs::String result;
                        result.data = _serial.read(_serial.available());
                        GripperComplete = (result.data.npos == result.data.find("ok"))?false:true;
                        if(GripperComplete == true)break;
                }
                ros::Duration(1).sleep();
	}
}

//pick and place? 2
void block_pose_write_callback(const geometry_msgs::Pose msg)
{
	if(GrabStart == true)
	{
		std::string Gcode = "";
		char poseX[10];
		char poseY[10];
		char poseZ[10];

		float x,y,z;
		x = msg.position.x * 1000;
		y = msg.position.y * 1000;
		z = 50;

		sprintf(poseX, "%.2f", x);
		sprintf(poseY, "%.2f", y);
		sprintf(poseZ, "%.2f", z);

		if(HomingComplete == true && CanMove == true)
		{
			Gcode = (std::string)"M3S40" + "\r\n";
	        	_serial.write(Gcode.c_str());
	                while (ros::ok())
	                {
	                        ros::Duration(0.1).sleep();
	                        std_msgs::String result;
	                        result.da


#include <iostream>
#include "frontend/impl/processor/simpleO3/llc.h"

namespace Ramulator {

SimpleO3LLC::SimpleO3LLC(int latency, int size_bytes, int linesize_bytes, int associativity, int num_mshrs):
m_latency(latency), m_size_bytes(size_bytes), m_linesize_bytes(linesize_bytes), m_associativity(associativity), m_num_mshrs(num_mshrs) {
  m_logger = Logging::create_logger("SimpleO3LLC");

  m_set_size = m_size_bytes / (m_linesize_bytes * m_associativity);
  m_index_mask = m_set_size - 1;
  m_index_offset = calc_log2(m_linesize_bytes);
  m_tag_offset = calc_log2(m_set_size) + m_index_offset;

  DEBUG_LOG(DSIMPLEO3LLC, m_logger, "Index mask: {0:x}", m_index_mask);
  DEBUG_LOG(DSIMPLEO3LLC, m_logger, "Index offset: {}",  m_index_offset);
  DEBUG_LOG(DSIMPLEO3LLC, m_logger, "Tag offset: {}",    m_tag_offset);
};

void SimpleO3LLC::tick() {
  m_clk++;

  // Send miss requests to the memory system when LLC latency is met
  // TODO: Optimization by assuming in-order issue?
  auto it = m_miss_list.begin();
  while (it != m_miss_list.end()) {
    if (m_clk >= it->first) {
      if (!m_memory_system->send(it->second)) {
        it++;
      }
      else {
        it = m_miss_list.erase(it);
      }
    } else {
      it++;
    }
  }

  // call hit request callback when LLC latency is met
  it = m_hit_list.begin();
  while (it != m_hit_list.end()) {
    if (m_clk >= it->first) {
      std::vector<Request> _req_v{it->second};
      m_receive_requests[it->second.addr] = _req_v;

      it->second.callback(it->second);
      it = m_hit_list.erase(it);
    }
    else {
      it++;
    }
  }
};

bool SimpleO3LLC::send(Request req) {
  CacheSet_t& set = get_set(req.addr);

  if (req.type_id == Request::Type::Read) {
    s_llc_read_access++;
  } else if (req.type_id == Request::Type::Write) {
    s_llc_write_access++;
  }

  if (auto line_it = check_set_hit(set, req.addr); line_it != set.end()) {
    // Hit in the set
    DEBUG_LOG(DSIMPLEO3LLC, m_logger,
    "[Clk={}] Request Source: {}, Type: {}, Addr: {}, Index: {}, Tag: {}. Hit, will finish at Clk={}",
    m_clk, req.source_id, req.type_id, req.addr, get_index(req.addr), get_tag(req.addr), m_clk, m_clk + m_latency
    );

    // Update the LRU status
    set.push_back({req.addr, get_tag(req.addr), line_it->dirty || (req.type_id == Request::Type::Write), true});
    set.erase(line_it);

    // Add to the hit list to callback when finished
    m_hit_list.push_back(std::make_pair(m_clk + m_latency, req));
    return true;
  } else {
    // Miss in the set
    DEBUG_LOG(DSIMPLEO3LLC, m_logger,
    "[Clk={}] Request Source: {}, Type: {}, Addr: {}, Index: {}, Tag: {}. Miss.",
    m_clk, req.source_id, req.type_id, req.addr, get_index(req.addr), get_tag(req.addr), m_clk, m_clk + m_latency
    );

    if (req.type_id == Request::Type::Read) {
      s_llc_read_misses++;
    } else if (req.type_id == Request::Type::Write) {
      s_llc_write_misses++;
    }

    bool dirty = (req.type_id == Request::Type::Write);
    if (req.type_id == Request::Type::Write) {
      req.type_id = Request::Type::Read;
    }

    // MSHR lookup
    auto mshr_it = check_mshr_hit(req.addr);
    if (mshr_it != m_mshrs.end()) {
      DEBUG_LOG(DSIMPLEO3LLC, m_logger,  "MSHR Hit.", m_clk);
      // Add new req to MSHR_requests
      m_receive_requests[mshr_it->first].push_back(req);

      mshr_it->second->dirty = dirty || mshr_it->second->dirty;
      return true;
    }

    // MSHR miss
    // Check if there is available MSHR entry
    if (m_mshrs.size() == m_num_mshrs) {
      DEBUG_LOG(DSIMPLEO3LLC, m_logger,  "No MSHR entry available.", m_clk);
      s_llc_mshr_unavailable++;
      return false;
    }

    // Check if there is available cache line in the set
    bool line_available = false;
    if (set.size() < m_associativity) {
      line_available = true;
    } else {
      for (const auto& line : set) {
        if (line.ready) {
          line_available = true;
        }
      }
    }
    if (!line_available) {
      DEBUG_LOG(DSIMPLEO3LLC, m_logger,  "No cache line available in the set.", m_clk);
      return false;
    }

    // Allocate a new cache line
    auto newline_it = allocate_line(set, req.addr);
    if (newline_it == set.end()) {
      // Should this happen?
      throw std::runtime_error("Failed to allocate new line when there is available entry.");
      return false;
    }
    newline_it->dirty = dirty;

    // Add to MSHR entries
    m_mshrs.push_back(std::make_pair(req.addr, newline_it));
    // Add Request to MSHR_requests
    std::vector<Request> _req_v{req};
    m_receive_requests[req.addr] = _req_v;

    // Add to the miss request list
    m_miss_list.push_back(std::make_pair(m_clk + m_latency, req));

    return true;
  }
};

void SimpleO3LLC::receive(Request& req) {
  auto it = std::find_if(
    m_mshrs.begin(), m


#include "Cache.h"

#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <map>

/**
 * Constructor to initialize the cache with specified parameters.
 *
 * @param sets Number of sets in the cache.
 * @param blocks Number of blocks (slots) per set.
 * @param bytes Number of bytes per block.
 * @param miss_write_type True for Write-Allocate, False for No-Write-Allocate.
 * @param hit_write_type True for Write-Back, False for Write-Through.
 * @param eviction_type True for LRU, False for FIFO.
 */
Cache::Cache(uint32_t sets, uint32_t blocks, uint32_t bytes,
             bool miss_write_type, bool hit_write_type, bool eviction_type)
    : num_sets(sets),
      num_slots(blocks),
      num_bytes(bytes),
      writes_per_block(num_bytes / 4),
      miss_write_type(miss_write_type),
      hit_write_type(hit_write_type),
      eviction_type(eviction_type),
      offset_size(log2(bytes)),
      index_size(log2(num_sets)),
      tag_size(32 - (offset_size + index_size)) {
    // Initialize each set with an empty map of tag-to-slot pointers
    cache = std::vector<Set>(num_sets, Set{std::map<uint32_t, Slot*>()});
}

// destructor
Cache::~Cache() {
    // Free all dynamically allocated slots in each set
    for (std::vector<Set>::iterator it = cache.begin(); it != cache.end();
         ++it) {
        Set& current_set = *it;

        // Deallocate each slot in the set
        for (auto& pair : current_set.index) {
            delete pair.second;  // Free memory for each slot
        }
    }
}

/**
 * Loads an address from the cache or memory.
 * Handles tag extraction, set lookup, hit/miss detection,
 * LRU/FIFO eviction, and updating cache state.
 *
 * @param address The memory address to load.
 * @return True if the load resulted in a cache hit, otherwise false.
 */
bool Cache::load(uint32_t address) {
    ++total_loads;   // Count the load operation
    ++current_time;  // Advance time for LRU/FIFO tracking

    // Extract offset, index, and tag from the address
    uint32_t index = get_index(address);
    uint32_t tag = get_tag(address);

    // Get the set corresponding to the index
    Set& current = cache[index];

    // Check for a hit
    if (current.index.find(tag) != current.index.end()) {
        ++load_hits;  // Cache hit

        // Update access time for LRU
        current.index[tag]->access_ts = current_time;

        total_cycles += cache_cost;  // Cost of accessing the cache
        return true;
    } else {
        ++load_misses;  // Cache miss

        // Add memory access and cache access costs
        total_cycles += cache_cost + (memory_cost * writes_per_block);

        if (current.index.size() < num_slots) {
            // Space available — insert new slot
            current.index[tag] = create_slot(tag);
        } else {
            // Set is full — need to evict
            uint32_t evict_tag;

            if (eviction_type) {
                // Use LRU policy
                uint32_t least_recent = UINT32_MAX;

                // find the least_recent set
                for (const auto& pair : current.index) {
                    Slot* current_slot = pair.second;

                    if (current_slot->access_ts < least_recent) {
                        evict_tag = pair.first;
                        least_recent = current_slot->access_ts;
                    }
                }

                assert(least_recent != UINT32_MAX);

            } else {
                // Use FIFO policy
                uint32_t oldest = UINT32_MAX;

                // find the onldest set
                for (const auto& pair : current.index) {
                    Slot* current_slot = pair.second;

                    if (current_slot->load_ts < oldest) {
                        evict_tag = pair.first;
                        oldest = current_slot->load_ts;
                    }
                }

                assert(oldest != UINT32_MAX);
            }

            // Replace evicted slot
            current.index[tag] = evict(current.index[evict_tag], tag);
            current.index.erase(evict_tag);
        }
        return false;
    }
}

/**
 * Stores to an address in the cache or memory.
 * Handles lookup, write policies, and updates.
 *
 * @param address The memory address to store.
 * @return True if store is a cache hit, otherwise false.
 */
bool Cache::store(uint32_t address) {
    ++total_stores;  // Count the store operation
    ++current_time;  // Advance time for LRU/FIFO tracking

    // Extract index and tag
    uint32_t index = get_index(address);
    uint32_t tag = get_tag(address);

    Set& current = cache[index];

    // Check for cache hit
    if (current.index.find(tag) != current.index.end()) {
        ++store_hits;  // Cache hit

        current.index[tag]->access_ts = current_time;

        if (hit_write_type) {
            // Write-back: write to cache, mark dirty
            total_cycles += cache_cost;
            current.index[tag]->dirty = true


//Getting started with the HC-SR04 ultrasonic sensor. Arduino Project Hub. (n.d.). Retrieved April 12, 2022, from https://create.arduino.cc/projecthub/Isaac100/getting-started-with-the-hc-sr04-ultrasonic-sensor-036380
// defines pins numbers, numbers 1-3 correspond to ultrasonic sensors (HC-SR04) 1-3
const int trigPin1 = 13;
const int echoPin1 = 12;
const int greenPin1 = 5;
const int yellowPin1 = 6;
const int redPin1 = 7;

const int trigPin2 = 11;
const int echoPin2 = 10;
const int greenPin2 = 24;
const int yellowPin2 = 22;
const int redPin2 = 23;

const int trigPin3 = 9;
const int echoPin3 = 8;
const int greenPin3 = 31;
const int yellowPin3 = 28;
const int redPin3 = 30;

// defines variables
long duration1;
long duration2;
long duration3;
int distance1;
int distance2;
int distance3;

void setup() {
  pinMode(trigPin1, OUTPUT); // Sets the trigPin as an Output
  pinMode(echoPin1, INPUT); // Sets the echoPin as an Input
  pinMode(greenPin1, OUTPUT);
  pinMode(yellowPin1, OUTPUT);
  pinMode(redPin1, OUTPUT);
  pinMode(trigPin2, OUTPUT);
  pinMode(echoPin2, INPUT);
  pinMode(greenPin2, OUTPUT);
  pinMode(yellowPin2, OUTPUT);
  pinMode(redPin2, OUTPUT);
  pinMode(trigPin3, OUTPUT);
  pinMode(echoPin3, INPUT);
  pinMode(greenPin3, OUTPUT);
  pinMode(yellowPin3, OUTPUT);
  pinMode(redPin3, OUTPUT);
  pinMode(2, OUTPUT);
  Serial.begin(4800);  // Starts the serial communication
}

void loop() {
  // Clears the trigPin
  digitalWrite(trigPin1, LOW);
  delayMicroseconds(2);
  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(trigPin1, HIGH);
  delayMicroseconds(4);
  digitalWrite(trigPin1, LOW);
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration1 = pulseIn(echoPin1, HIGH);
  // Calculating the distance
  distance1 = duration1 * 0.034 / 2;
  // Prints the distance on the Serial Monitor
  Serial.print("Distance1: ");
  Serial.println(distance1);

//for any distance larger than 60cm none of the leds light up
if(distance1 > 60)
 {
  digitalWrite(redPin1, LOW);
  digitalWrite(yellowPin1, LOW);
  digitalWrite(greenPin1, LOW);
 }
  //if distance is less than 60cm or greater than 40cm than output green for okay
  elseif(distance <= 60 && distance > 40)
  {digitalWrite(redPin1, LOW);
  digitalWrite(yellowPin1, LOW);
    digitalWrite(greenPin1, HIGH);
  }
  //if distance is less than 40cm or greater than 15cm than output yellow to signify the sensor is nearing the object
  else if (distance <= 40 && distance > 15)
  {
    digitalWrite(redPin1, LOW);
    digitalWrite(greenPin1, LOW);
    digitalWrite(yellowPin1, HIGH);
  }
  //if distance is less than 15cm then the red led lights up since it is the most urgent color
  else if (distance <= 15)
  {
    digitalWrite(greenPin1, LOW);
    digitalWrite(yellowPin1, LOW);
    digitalWrite(redPin1, HIGH);
  }

//The same process as above is repeated for sensor 2 and sensor 3
 // SENSOR 2
  digitalWrite(trigPin2, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin2, HIGH);
  delayMicroseconds(4);
  digitalWrite(trigPin2, LOW);
  duration2 = pulseIn(echoPin2, HIGH);
  distance2 = duration2 * 0.034 / 2;
  Serial.print("Distance2: ");
  Serial.println(distance2);
 if(distance2 > 60)
 {
 digitalWrite(redPin2, LOW);
 digitalWrite(yellowPin2, LOW);
 digitalWrite(greenPin2, LOW);
 }
  else if(distance2 <= 60 && distance2 > 40)
  {
  digitalWrite(redPin2, LOW);
  digitalWrite(yellowPin2, LOW);
  digitalWrite(greenPin2, HIGH);
  }
  else if (distance2 <= 40 && distance2 > 15)
  {
    digitalWrite(redPin2, LOW);
    digitalWrite(greenPin2, LOW);
    digitalWrite(yellowPin2, HIGH);
  }
  else if (distance2 < 15)
  {
    digitalWrite(greenPin2, LOW);
    digitalWrite(yellowPin2, LOW);
    digitalWrite(redPin2, HIGH);
  }
 // SENSOR 3
  digitalWrite(trigPin3, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin3, HIGH);
  delayMicroseconds(4);
  digitalWrite(trigPin3, LOW);
  duration3 = pulseIn(echoPin3, HIGH);
  distance3 = duration3 * 0.034 / 2;
  Serial.print("Distance3: ");
  Serial.println(distance3);
 if(distance3 > 60)
 {
  digitalWrite(redPin3, LOW);
 digitalWrite(yellowPin3, LOW);
 digitalWrite(greenPin3, LOW);
 }
  else if(distance3 <= 60 && distance3 > 40)
  {
  digitalWrite(redPin3, LOW);
  digitalWrite(yellowPin3, LOW);
  digitalWrite(greenPin3, HIGH);
  }
  else if (distance3 <= 40 && distance3 > 15)
  {
    digitalWrite(redPin3, LOW);
    digitalWrite(greenPin3, LOW);
    digitalWrite(yellowPin3, HIGH);
  }
  else if (distance3 < 15)
  {
    digitalWrite(greenPin3, LOW);
    digitalWrite(yellowPin3, LOW);
    digitalWrite(redPin3, HIGH);
    }

//Now we are identifying which sensor is measuring the shortest distance at that given moment and what that distance is
    int distanceMin = 10000;
distanceMin = (distanceMin > distance1) ? distance1 : distanceMin;
dist


#include "TcpClientDialog.h"
#include "ui_TcpClientDialog.h"
#include <QHostAddress>
#include <QMessageBox>
#include <QTcpSocket>

TcpClientDialog::TcpClientDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::TcpClientDialog),
    socket(new QTcpSocket(this))
{
    ui->setupUi(this);

    connect(socket, &QTcpSocket::connected, this, &TcpClientDialog::onConnected);
    connect(socket, &QTcpSocket::disconnected, this, &TcpClientDialog::onDisconnected);
    connect(socket, &QTcpSocket::readyRead, this, &TcpClientDialog::onReadyRead);
    connect(ui->lineEditMessage, &QLineEdit::returnPressed,
            this, &TcpClientDialog::on_sendButton_clicked);
}

TcpClientDialog::~TcpClientDialog()
{
    delete ui;
}
bool TcpClientDialog::ValidateConnect()
{
    QString host = ui->lineEditHost->text().trimmed();
    QString portStr = ui->lineEditPort->text().trimmed();

    // Check if host/IP is empty
    if (host.isEmpty()) {
        QMessageBox::warning(this, "Input Error", "Please enter a valid host/IP address.");
        return false;
    }

    // Validate host/IP format
    QHostAddress address;
    if (!address.setAddress(host)) {
        QMessageBox::warning(this, "Input Error", "Invalid IP address or hostname.");
        return false;
    }

    // Validate port
    bool ok;
    quint16 port = portStr.toUShort(&ok);
    if (!ok || port == 0 || port > 65535) {
        QMessageBox::warning(this, "Input Error", "Please enter a valid port number (1-65535).");
        return false;
    }
    return true;
}
void TcpClientDialog::on_connectButton_clicked()
{
    if(ValidateConnect())
    {
        socket->connectToHost(ui->lineEditHost->text().trimmed(), ui->lineEditPort->text().toUShort());
        connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onSocketError(QAbstractSocket::SocketError)));
    }
}
void TcpClientDialog::onSocketError(QAbstractSocket::SocketError socketError)
{
    Q_UNUSED(socketError);
    QMessageBox::critical(this, "Connection Failed",
                          "Cannot connect to the server.\n"
                          "Please make sure the server is running and IP/port are correct.");
}

void TcpClientDialog::on_disconnectButton_clicked()
{
    if (!socket) return; // safety check

    if (socket->state() == QAbstractSocket::ConnectedState ||
            socket->state() == QAbstractSocket::ConnectingState)
    {
        ui->textEditIncoming->append("Disconnecting...");
        socket->disconnectFromHost();
    }
    else
    {
        QMessageBox::information(this, "Disconnect", "Socket is not connected.");
    }
}

void TcpClientDialog::on_sendButton_clicked()
{
    if (!socket) return; // safety check

    // Check connection
    if (socket->state() != QAbstractSocket::ConnectedState) {
        QMessageBox::warning(this, "Send Error", "Not connected to server.");
        return;
    }

    QString message = ui->lineEditMessage->text().trimmed();
    if (message.isEmpty()) {
        QMessageBox::warning(this, "Send Error", "Please enter a message to send.");
        return;
    }

    // Send message
    qint64 bytesSent = socket->write(message.toUtf8());
    if (bytesSent == -1) {
        QMessageBox::warning(this, "Send Error", "Failed to send the message.");
    } else {
        ui->textEditIncoming->append("You: " + message);
        ui->lineEditMessage->clear();
    }
}

void TcpClientDialog::on_clearButton_clicked()
{
    ui->textEditIncoming->clear();
    ui->lineEditMessage->clear();
}

void TcpClientDialog::onConnected()
{
    ui->textEditIncoming->append("Connected to server.");
}

void TcpClientDialog::onDisconnected()
{
    ui->textEditIncoming->append("Disconnected.");
}

void TcpClientDialog::onReadyRead()
{
    QByteArray data = socket->readAll();
    ui->textEditIncoming->append("Server: " + QString::fromUtf8(data));
}


#include "parser.h"
#include "error.h"
#include <iostream>
#include <sstream>
#include <cctype>
using std::cin;
using std::cout;
using std::endl;
using std::stringstream;

void Parser::Expr(){
    //expr -> term add
    Term();
    while(true){ //add aqui
            //add -> + term {print(+)} add
            if(lookahead -> tag == '+'){
                Match('+');
                Term();
                cout << '+';
            }
            //add -> - term {print(-)} add
            if(lookahead -> tag == '-'){
                    Match('-');
                    Term();
                    cout << '-';
            }
            // add -> epsilon
            else return;
    }
}

void Parser::Term(){
    //term -> fact mult
    Fact();
    while(true){
        //mult -> * fact {print(*)} mult
        if(lookahead -> tag == '*'){
            Match('*');
            Fact();
            cout << '*';
        }
        // mult -> / fact {print(/)} mult
        if(lookahead -> tag == '/'){
            Match('/');
            Fact();
            cout << '/';
        }
        // mult -> epsilon
        else return;
    }
}

void Parser::Fact(){
    //fact -> (expr)
    if(lookahead -> tag == '('){
        Match('(');
        Expr();
        if(!Match(')')){
            throw SyntaxError{ scanner.Lineno(), "\')\' esperado"};
        }
    }
    //fact -> num {print(num.valor)}
    else if (lookahead -> tag == Tag::NUM){
        cout << '[' << lookahead->toString() << ']';
        Match(Tag::NUM);
    }
    //fact -> id {print(id.nome)}
    else if(lookahead -> tag == Tag::ID){
        cout << '[' << lookahead->toString()<<']';
        Match(Tag::ID); // nao precisaria pois ja sabemos que é verdade e deveria ser antes do print por ser pos fixada mas enfim so por questao didatica
    }
    //erro de sintaxe
    else{
        stringstream ss;
        ss << "simbolo \'" << lookahead -> toString() << "\' invalido";
        throw SyntaxError{scanner.Lineno(), ss.str()};
    }
}

bool Parser::Match(int tag){
    if(tag == lookahead->tag){
        lookahead = scanner.Scan();
        return true;
    }
    return false;
}

Parser::Parser(){
    lookahead = scanner.Scan();
}

void Parser::Start(){
    Expr(); // chama o simbolo inicial da gramatica
    //como o salto de linha nao gera mais um token espera-se EOF(ctrl + d)
    if(lookahead -> tag != EOF){
        stringstream ss;
        ss << "símbolo \'" << lookahead -> toString() << "\' inválido";
        throw SyntaxError{scanner.Lineno(), ss.str()};
    }
}


#include <bits/stdc++.h>
using namespace std;

const int MAX_N = 1005; // Max grid size
int n, m; // Grid dimensions
char grid[MAX_N][MAX_N]; // Grid content
bool visited[MAX_N][MAX_N]; // 2D visited array
int dist[MAX_N][MAX_N]; // Distance array
int dx[4] = {1, -1, 0, 0}; // 4-directional moves: down, up, right, left
int dy[4] = {0, 0, 1, -1};

// BFS to compute component size and distances
int bfs(int start_x, int start_y) {
    queue<pair<int, int>> q;
    q.push({start_x, start_y});
    visited[start_x][start_y] = true;
    dist[start_x][start_y] = 0;
    int component_size = 1; // Count starting cell

    while (!q.empty()) {
        auto [x, y] = q.front();
        q.pop();

        // Explore 4 directions
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];

            if (nx >= 0 && nx < n && ny >= 0 && ny < m && !visited[nx][ny] && grid[nx][ny] != '#') {
                visited[nx][ny] = true;
                dist[nx][ny] = dist[x][y] + 1;
                q.push({nx, ny});
                component_size++;
            }
        }
    }
    return component_size;
}

int main() {
    cin >> n >> m;
    // Read grid
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> grid[i][j];
            visited[i][j] = false;
            dist[i][j] = -1; // Initialize distances to -1 (unreachable)
        }
    }

    // Example: BFS from (0,0)
    if (grid[0][0] != '#') {
        int component_size = bfs(0, 0);
        cout << "Component size: " << component_size << endl;

        // Print distances to all reachable cells
        cout << "Distances from (0,0):\n";
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                cout << dist[i][j] << " ";
            }
            cout << endl;
        }
    } else {
        cout << "Starting cell is blocked" << endl;
    }

    return 0;
}


/*
 * si5351.cpp - Si5351 library for Arduino
 *
 * Copyright (C) 2015 - 2019 Jason Milldrum <milldrum@gmail.com>
 *                           Dana H. Myers <k6jq@comcast.net>
 *
 * Modifications by Ian Mitchell
 *  2025-03-05 remove new and delete (replace with stack storage)
 *
 * Some tuning algorithms derived from clk-si5351.c in the Linux kernel.
 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
 * Rabeeh Khoury <rabeeh@solid-run.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdint.h>

#include "Arduino.h"
#include "Wire.h"
#include "si5351.h"

/********************/
/* Public functions */
/********************/

Si5351::Si5351(uint8_t i2c_addr):
	i2c_bus_addr(i2c_addr)
{
	xtal_freq[0] = SI5351_XTAL_FREQ;

	// Start by using XO ref osc as default for each PLL
	plla_ref_osc = SI5351_PLL_INPUT_XO;
	pllb_ref_osc = SI5351_PLL_INPUT_XO;
	clkin_div = SI5351_CLKIN_DIV_1;
}

/*
 * init(uint8_t xtal_load_c, uint32_t ref_osc_freq, int32_t corr)
 *
 * Setup communications to the Si5351 and set the crystal
 * load capacitance.
 *
 * xtal_load_c - Crystal load capacitance. Use the SI5351_CRYSTAL_LOAD_*PF
 * defines in the header file
 * xo_freq - Crystal/reference oscillator frequency in 1 Hz increments.
 * Defaults to 25000000 if a 0 is used here.
 * corr - Frequency correction constant in parts-per-billion
 *
 * Returns a boolean that indicates whether a device was found on the desired
 * I2C address.
 *
 */
bool Si5351::init(uint8_t xtal_load_c, uint32_t xo_freq, int32_t corr)
{
	// Start I2C comms
	Wire.begin();

	// Check for a device on the bus, bail out if it is not there
	Wire.beginTransmission(i2c_bus_addr);
	uint8_t reg_val;
  reg_val = Wire.endTransmission();

	if(reg_val == 0)
	{
		// Wait for SYS_INIT flag to be clear, indicating that device is ready
		uint8_t status_reg = 0;
		do
		{
			status_reg = si5351_read(SI5351_DEVICE_STATUS);
		} while (status_reg >> 7 == 1);

		// Set crystal load capacitance
		si5351_write(SI5351_CRYSTAL_LOAD, (xtal_load_c & SI5351_CRYSTAL_LOAD_MASK) | 0b00010010);

		// Set up the XO and CLKIN reference frequencies
		if (xo_freq != 0)
		{
			set_ref_freq(xo_freq, SI5351_PLL_INPUT_XO);
      set_ref_freq(xo_freq, SI5351_PLL_INPUT_CLKIN);          //Also CLKIN
		}
		else
		{
			set_ref_freq(SI5351_XTAL_FREQ, SI5351_PLL_INPUT_XO);
      set_ref_freq(SI5351_XTAL_FREQ, SI5351_PLL_INPUT_CLKIN); //Also CLKIN
		}

		// Set the frequency calibrations for the XO and CLKIN
		set_correction(corr, SI5351_PLL_INPUT_XO);
    set_correction(corr, SI5351_PLL_INPUT_CLKIN);

		reset();

		return true;
	}
	else
	{
		return false;
	}
}

/*
 * reset(void)
 *
 * Call to reset the Si5351 to the state initialized by the library.
 *
 */
void Si5351::reset(void)
{
	// Initialize the CLK outputs according to flowchart in datasheet
	// First, turn them off
	si5351_write(16, 0x80);
	si5351_write(17, 0x80);
	si5351_write(18, 0x80);
	si5351_write(19, 0x80);
	si5351_write(20, 0x80);
	si5351_write(21, 0x80);
	si5351_write(22, 0x80);
	si5351_write(23, 0x80);

	// Turn the clocks back on...
	si5351_write(16, 0x0c);
	si5351_write(17, 0x0c);
	si5351_write(18, 0x0c);
	si5351_write(19, 0x0c);
	si5351_write(20, 0x0c);
	si5351_write(21, 0x0c);
	si5351_write(22, 0x0c);
	si5351_write(23, 0x0c);

	// Set PLLA and PLLB to 800 MHz for automatic tuning
	set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
	set_pll(SI5351_PLL_FIXED, SI5351_PLLB);

	// Make PLL to CLK assignments for automatic tuning
	pll_assignment[0] = SI5351_PLLA;
	pll_assignment[1] = SI5351_PLLA;
	pll_assignment[2] = SI5351_PLLA;
	pll_assignment[3] = SI5351_PLLA;
	pll_assignment[4] = SI5351_PLLA;
	pll_assignment[5] = SI5351_PLLA;
	pll_assignment[6] = SI5351_PLLB;
	pll_assignment[7] = SI5351_PLLB;

	set_ms_source(SI5351_CLK0, SI5351_PLLA);
	set_ms_source(SI5351_CLK1, SI5351_PLLA);
	set_ms_source(SI5351_CLK2, SI5351_PLLA);
	set_ms_source(SI5351_CLK3, SI5351_PLLA);
	set_ms_source(SI5351_CLK4, SI5351_PLLA);
	set_ms_source(SI5351_CLK5, SI5351_PLLA);
	set_ms_source(SI5351_CLK6, SI5351_PLLB);
	set_ms_source(SI5351_CLK7, SI5351_PLLB);

	// Reset the VCXO param
	si5351_write(SI5351_VXCO_PARAMETERS_LOW, 0);
	si5351_write(SI5351_VXCO_PARAMETERS_MID, 0);
	si5351_write(SI5351_VXCO_PARAMETERS_HIGH, 0);

	// Then reset the PLLs
	pll_reset(SI5351_PLLA);
	pll_reset(SI5351_PLLB);

	// Set initial frequencies
	uint8_t i;
	for(i = 0; i < 8; i++)
	{
		clk_freq[i] =


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

/**
 * @file ActuatorEffectivenessTailsitterVTOL.hpp
 *
 * Actuator effectiveness for tailsitter VTOL
 */

#include "ActuatorEffectivenessTailsitterVTOL.hpp"

using namespace matrix;

ActuatorEffectivenessTailsitterVTOL::ActuatorEffectivenessTailsitterVTOL(ModuleParams *parent)
	: ModuleParams(parent), _mc_rotors(this), _control_surfaces(this)
{
	setFlightPhase(FlightPhase::HOVER_FLIGHT);
}
bool
ActuatorEffectivenessTailsitterVTOL::getEffectivenessMatrix(Configuration &configuration,
		EffectivenessUpdateReason external_update)
{
	if (external_update == EffectivenessUpdateReason::NO_EXTERNAL_UPDATE) {
		return false;
	}

	// MC motors
	configuration.selected_matrix = 0;
	// enable MC yaw control if more than 3 rotors
	_mc_rotors.enableYawByDifferentialThrust(_mc_rotors.geometry().num_rotors > 3);
	const bool mc_rotors_added_successfully = _mc_rotors.addActuators(configuration);

	// Control Surfaces
	configuration.selected_matrix = 1;
	_first_control_surface_idx = configuration.num_actuators_matrix[configuration.selected_matrix];
	const bool surfaces_added_successfully = _control_surfaces.addActuators(configuration);

	return (mc_rotors_added_successfully && surfaces_added_successfully);
}

void ActuatorEffectivenessTailsitterVTOL::allocateAuxilaryControls(const float dt, int matrix_index,
		ActuatorVector &actuator_sp)
{
	if (matrix_index == 1) {
		// apply flaps
		normalized_unsigned_setpoint_s flaps_setpoint;

		if (_flaps_setpoint_sub.copy(&flaps_setpoint)) {
			_control_surfaces.applyFlaps(flaps_setpoint.normalized_setpoint, _first_control_surface_idx, dt, actuator_sp);
		}

		// apply spoilers
		normalized_unsigned_setpoint_s spoilers_setpoint;

		if (_spoilers_setpoint_sub.copy(&spoilers_setpoint)) {
			_control_surfaces.applySpoilers(spoilers_setpoint.normalized_setpoint, _first_control_surface_idx, dt, actuator_sp);
		}
	}
}

void ActuatorEffectivenessTailsitterVTOL::updateSetpoint(const matrix::Vector<float, NUM_AXES> &control_sp,
		int matrix_index, ActuatorVector &actuator_sp, const matrix::Vector<float, NUM_ACTUATORS> &actuator_min,
		const matrix::Vector<float, NUM_ACTUATORS> &actuator_max)
{
	if (matrix_index == 0) {
		stopMaskedMotorsWithZeroThrust(_forwards_motors_mask, actuator_sp);
	}
}

void ActuatorEffectivenessTailsitterVTOL::setFlightPhase(const FlightPhase &flight_phase)
{
	if (_flight_phase == flight_phase) {
		return;
	}

	ActuatorEffectiveness::setFlightPhase(flight_phase);

	// update stopped motors
	switch (flight_phase) {
	case FlightPhase::FORWARD_FLIGHT:
		_forwards_motors_mask = _mc_rotors.getUpwardsMotors(); // allocation frame they stay upwards
		break;

	case FlightPhase::HOVER_FLIGHT:
	case FlightPhase::TRANSITION_FF_TO_HF:
	case FlightPhase::TRANSITION_HF_TO_FF:
		_forwards_motors_mask = 0;
		_stopped_motors_mask = 0;
		break;
	}
}


/*
 * This code is licensed under the GNU AGPLv3
 * Copyright (c) 2025 GokbakarE
 * Date: 28-08-2025
 */
#include "SuperH3.hpp"
#include <iostream>
#include <bitset>
#include <unordered_map>
#include <string>
#include <string_view>
#include <format>

static const std::unordered_map<std::string_view, std::string_view> OpcodeMap = {
    {"0011nnnnmmmm1100", "ADD $M, $N"},
    {"0011nnnnmmmm1110", "ADDC $M, $N"},
    {"0011nnnnmmmm1111", "ADDV $M, $N"},
    {"0010nnnnmmmm1001", "AND $M, $N"},
    {"11001001iiiiiiii", "AND $I, R0"},
    {"11001101iiiiiiii", "AND.B $I, @(R0, GBR)"},
    {"10001011dddddddd", "BF $D"},
    {"10001111dddddddd", "BF/S $D"},
    {"1010ffffffffffff", "BRA $F"},
    {"0000nnnn00100011", "BRAF $N"},
    {"1011ffffffffffff", "BSR $F"},
    {"0000nnnn00000011", "BSRF $N"},
    {"10001001dddddddd", "BT $D"},
    {"10001101dddddddd", "BT/S $D"},
    {"0000000000101000", "CLRMAC"},
    {"0000000001001000", "CLRS"},
    {"0000000000001000", "CLRT"},
    {"0011nnnnmmmm0000", "CMP/EQ $M, $N"},
    {"0011nnnnmmmm0011", "CMP/GE $M, $N"},
    {"0011nnnnmmmm0111", "CMP/GT $M, $N"},
    {"0011nnnnmmmm0110", "CMP/HI $M, $N"},
    {"0011nnnnmmmm0010", "CMP/HS $M, $N"},
    {"0100nnnn00010101", "CMP/PL $N"},
    {"0100nnnn00010001", "CMP/PZ $N"},
    {"0010nnnnmmmm1100", "CMP/STR $M, $N"},
    {"10001000iiiiiiii", "CMP/EQ $I, R0"},
    {"0010nnnnmmmm0111", "DIV0S $M, $N"},
    {"0000000000011001", "DIV0U"},
    {"0011nnnnmmmm0100", "DIV1 $M, $N"},
    {"0011nnnnmmmm1101", "DMULS.L $M, $N"},
    {"0011nnnnmmmm0101", "DMULU.L $M, $N"},
    {"0100nnnn00010000", "DT $N"},
    {"0110nnnnmmmm1110", "EXTS.B $M, $N"},
    {"0110nnnnmmmm1111", "EXTS.W $M, $N"},
    {"0110nnnnmmmm1100", "EXTU.B $M, $N"},
    {"0110nnnnmmmm1101", "EXTU.W $M, $N"},
    {"0100nnnn00101011", "JMP @$N"},
    {"0100nnnn00001011", "JSR @$N"},
    {"0100nnnn00001110", "LDC $N, SR"},
    {"0100nnnn00011110", "LDC $N, GBR"},
    {"0100nnnn00101110", "LDC $N, VBR"},
    {"0100nnnn00111110", "LDC $N, SSR"},
    {"0100nnnn01001110", "LDC $N, SPC"},
    {"0100nnnn10001110", "LDC $N, R0_BANK"},
    {"0100nnnn10011110", "LDC $N, R1_BANK"},
    {"0100nnnn10101110", "LDC $N, R2_BANK"},
    {"0100nnnn10111110", "LDC $N, R3_BANK"},
    {"0100nnnn11001110", "LDC $N, R4_BANK"},
    {"0100nnnn11011110", "LDC $N, R5_BANK"},
    {"0100nnnn11101110", "LDC $N, R6_BANK"},
    {"0100nnnn11111110", "LDC $N, R7_BANK"},
    {"0100nnnn00000111", "LDC.L @$N+, SR"},
    {"0100nnnn00010111", "LDC.L @$N+, GBR"},
    {"0100nnnn00100111", "LDC.L @$N+, VBR"},
    {"0100nnnn00110111", "LDC.L @$N+, SSR"},
    {"0100nnnn01000111", "LDC.L @$N+, SPC"},
    {"0100nnnn10000111", "LDC.L @$N+, R0_BANK"},
    {"0100nnnn10010111", "LDC.L @$N+, R1_BANK"},
    {"0100nnnn10100111", "LDC.L @$N+, R2_BANK"},
    {"0100nnnn10110111", "LDC.L @$N+, R3_BANK"},
    {"0100nnnn11000111", "LDC.L @$N+, R4_BANK"},
    {"0100nnnn11010111", "LDC.L @$N+, R5_BANK"},
    {"0100nnnn11100111", "LDC.L @$N+, R6_BANK"},
    {"0100nnnn11110111", "LDC.L @$N+, R7_BANK"},
    {"0100nnnn00001010", "LDS $N, MACH"},
    {"0100nnnn00011010", "LDS $N, MACL"},
    {"0100nnnn00101010", "LDS $N, PR"},
    {"0100nnnn00000110", "LDS.L @$N+, MACH"},
    {"0100nnnn00010110", "LDS.L @$N+, MACL"},
    {"0100nnnn00100110", "LDS.L @$N+, PR"},
    {"0000000000111000", "LDTLB"},
    {"0000nnnnmmmm1111", "MAC.L $M, $N"},
    {"0100nnnnmmmm1111", "MAC.W $M, $N"},
    {"0110nnnnmmmm0011", "MOV $M, $N"},
    {"0010nnnnmmmm0000", "MOV.B $M, @$N"},
    {"0010nnnnmmmm0001", "MOV.W $M, @$N"},
    {"0010nnnnmmmm0010", "MOV.L $M, @$N"},
    {"0110nnnnmmmm0000", "MOV.B @$M, $N"},
    {"0110nnnnmmmm0001", "MOV.W @$M, $N"},
    {"0110nnnnmmmm0010", "MOV.L @$M, $N"},
    {"0010nnnnmmmm0100", "MOV.B $M, @-$N"},
    {"0010nnnnmmmm0101", "MOV.W $M, @-$N"},
    {"0010nnnnmmmm0110", "MOV.L $M, @-$N"},
    {"0110nnnnmmmm0100", "MOV.B @$M+, $N"},
    {"0110nnnnmmmm0101", "MOV.W @$M+, $N"},
    {"0110nnnnmmmm0110", "MOV.L @$M+, $N"},
    {"0000nnnnmmmm0100", "MOV.B $M, @(R0, $N)"},
    {"0000nnnnmmmm0101", "MOV.W $M, @(R0, $N)"},
    {"0000nnnnmmmm0110", "MOV.L $M, @(R0, $N)"},
    {"0000nnnnmmmm1100", "MOV.B @(R0, $M), $N"},
    {"0000nnnnmmmm1101", "MOV.W @(R0, $M), $N"},
    {"0000nnnnmmmm1110", "MOV.L @(R0, $M), $N"},
    {"1110nnnniiiiiiii", "MOV $I, $N"},
    {"1001nnnnpppppppp", "MOV.W @($P, PC), $N"},
    {"1101nnnnpppppppp", "MOV.L @($P, PC), $N"},
    {"11000100pppppppp", "MOV.B @($P, GBR), R0"},
    {"11000101pppppppp", "MOV.W @($P, GBR), R0"},
    {"11000110pppppppp", "MOV.L @($P, GBR), R0"},
    {"11000000pppppppp", "MOV.B R0, @($P, GBR)"},
    {"11000001pppppppp", "MOV.W R0, @($P, GBR)"},
    {"11000010pppppppp", "MOV.L R0, @($P, GBR)"},
    {"10000000mmmmssss", "MOV.B R0, @($S, $M)"},
    {"10000001mmmmssss", "MOV.W R0, @($S, $M)"},
    {"0001nnnnmmmmssss", "MOV.L $M, @($S, $N)"},
    {"10000100mmmmssss", "MOV.B @($S, $M), R0"},
    {"10000101mmmmssss", "MOV.W @($S, $M), R0"},
    {"0101nnnnmmmmssss", "MOV.L @($S, $N), $M"},
    {"1


// main.cpp - DX12 Hello Triangle (Win32, x64)
// Compilar con: d3d12.lib, dxgi.lib, d3dcompiler.lib
// Requiere Windows 10 SDK o superior.

#include <windows.h>
#include <wrl/client.h>
#include <d3d12.h>
#include <dxgi1_6.h>
#include <d3dcompiler.h>
#include <DirectXMath.h>
#include <string>
#include <stdexcept>
#include <vector>

#pragma comment(lib, "d3d12.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3dcompiler.lib")

using Microsoft::WRL::ComPtr;
using namespace DirectX;

#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p) if (p) { (p)->Release(); (p) = nullptr; }
#endif

// --- Config ---
static const UINT FrameCount = 2;
static UINT g_Width = 1280;
static UINT g_Height = 720;

// --- Win32 ---
HINSTANCE g_hInst = nullptr;
HWND g_hWnd = nullptr;

// --- DX12 core ---
ComPtr<ID3D12Device>            g_Device;
ComPtr<IDXGISwapChain3>         g_SwapChain;
ComPtr<ID3D12CommandQueue>      g_CommandQueue;
ComPtr<ID3D12DescriptorHeap>    g_RTVHeap;
UINT                            g_RTVDescriptorSize = 0;
ComPtr<ID3D12Resource>          g_RenderTargets[FrameCount];
ComPtr<ID3D12CommandAllocator>  g_CommandAllocators[FrameCount];
ComPtr<ID3D12GraphicsCommandList> g_CommandList;
ComPtr<ID3D12Fence>             g_Fence;
UINT64                          g_FenceValues[FrameCount] = {};
HANDLE                          g_FenceEvent = nullptr;
UINT                            g_FrameIndex = 0;

// --- Pipeline state ---
ComPtr<ID3D12RootSignature>     g_RootSignature;
ComPtr<ID3D12PipelineState>     g_PSO;

// --- Geometry ---
struct Vertex { XMFLOAT3 pos; XMFLOAT3 color; };
ComPtr<ID3D12Resource>          g_VertexBuffer;
D3D12_VERTEX_BUFFER_VIEW        g_VBView = {};

// --- Viewport/Scissor ---
D3D12_VIEWPORT                  g_Viewport = {};
D3D12_RECT                      g_ScissorRect = {};

// --------------------------------- Helpers ---------------------------------

inline void ThrowIfFailed(HRESULT hr)
{
    if (FAILED(hr)) throw std::runtime_error("HRESULT failed.");
}

#if defined(_DEBUG)
void EnableDebugLayer()
{
    ComPtr<ID3D12Debug> debug;
    if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debug))))
    {
        debug->EnableDebugLayer();
    }
}
#endif

static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    case WM_SIZE:
        // (Opcional) Manejar resize. Para simplicity, lo ignoramos en este sample.
        return 0;
    default:
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
}

void WaitForGPU()
{
    const UINT64 fenceToWait = ++g_FenceValues[g_FrameIndex];
    ThrowIfFailed(g_CommandQueue->Signal(g_Fence.Get(), fenceToWait));

    if (g_Fence->GetCompletedValue() < fenceToWait)
    {
        ThrowIfFailed(g_Fence->SetEventOnCompletion(fenceToWait, g_FenceEvent));
        WaitForSingleObject(g_FenceEvent, INFINITE);
    }
}

void MoveToNextFrame()
{
    const UINT64 currentFenceValue = ++g_FenceValues[g_FrameIndex];
    ThrowIfFailed(g_CommandQueue->Signal(g_Fence.Get(), currentFenceValue));

    g_FrameIndex = g_SwapChain->GetCurrentBackBufferIndex();

    if (g_Fence->GetCompletedValue() < g_FenceValues[g_FrameIndex])
    {
        ThrowIfFailed(g_Fence->SetEventOnCompletion(g_FenceValues[g_FrameIndex], g_FenceEvent));
        WaitForSingleObject(g_FenceEvent, INFINITE);
    }
}

// ------------------------------- Init DX12 ----------------------------------

void CreateWindowClassAndWindow()
{
    const wchar_t* CLASS_NAME = L"DX12WindowClass";

    WNDCLASSEX wc = {};
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.lpfnWndProc = WndProc;
    wc.hInstance = g_hInst;
    wc.lpszClassName = CLASS_NAME;
    wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wc.style = CS_HREDRAW | CS_VREDRAW;

    RegisterClassEx(&wc);

    RECT rc = { 0, 0, (LONG)g_Width, (LONG)g_Height };
    AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);

    g_hWnd = CreateWindowEx(
        0, CLASS_NAME, L"DX12 Hello Triangle",
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
        rc.right - rc.left, rc.bottom - rc.top,
        nullptr, nullptr, g_hInst, nullptr);

    ShowWindow(g_hWnd, SW_SHOW);
}

void CreateDeviceAndSwapchain()
{
    UINT dxgiFactoryFlags = 0;

#if defined(_DEBUG)
    // Si el Debug Layer está habilitado y fallan validaciones, se mostrarán en Output.
    EnableDebugLayer();
    dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
#endif

    ComPtr<IDXGIFactory6> factory;
    ThrowIfFailed(CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory)));

    // Crear dispositivo (usar el adaptador por defecto)
    ThrowIfFailed(D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&g_Device)));

    // Command queue
    D3D12_COMMAND_QUEUE_DESC qdesc = {};
    qdesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
    qdesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
    qdesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
    qdesc.NodeMask = 0;
    Thr


#include <algorithm>
#include <chrono>
#include <format>
#include <iomanip>
#include <numeric>
#include <random>
#include <ranges>
#include <thread>
#include <vector>

#include <evolab/evolab.hpp>
#include <evolab/parallel/tbb_executor.hpp>

#include "test_helper.hpp"

namespace {

// Explicit using declarations in narrowest possible scope following C++23 best practices
// Provides clear dependency tracking while preventing namespace pollution and improving
// compile-time performance through selective symbol importation
using evolab::core::Fitness;
using evolab::parallel::TBBExecutor;
using evolab::problems::create_random_tsp;
using evolab::problems::TSP;

// Generate test population using C++20 ranges for modern, expressive code
std::vector<TSP::GenomeT> create_test_population(const TSP& tsp, std::size_t population_size,
                                                 std::uint32_t seed = 123) {
    std::vector<TSP::GenomeT> population(population_size);
    // Deterministic seeding for reproducible tests across runs
    // Using seed_seq with deterministic values to properly initialize mt19937 state space
    std::seed_seq seed_seq{seed, seed + 1, seed + 2, seed + 3};
    std::mt19937 rng(seed_seq);
    std::ranges::generate(population, [&tsp, &rng] { return tsp.random_genome(rng); });
    return population;
}

// Sequential evaluation for comparison using C++20 ranges for functional-style processing
std::vector<Fitness> evaluate_sequential(const TSP& tsp,
                                         const std::vector<TSP::GenomeT>& population) {
    std::vector<Fitness> fitnesses(population.size());
    std::ranges::transform(population, fitnesses.begin(),
                           [&tsp](const auto& genome) { return tsp.evaluate(genome); });
    return fitnesses;
}

// Test functions using modern C++ anonymous namespace idiom instead of static
// for internal linkage, providing better consistency and type definition support
[[nodiscard]] bool test_parallel_evaluation_correctness() {
    TestResult result;

    auto tsp = create_random_tsp(12, 100.0, 42);
    auto population = create_test_population(tsp, 50);

    // Sequential evaluation
    auto sequential_fitnesses = evaluate_sequential(tsp, population);

    // Parallel evaluation using TBB executor
    TBBExecutor executor; // Stateless deterministic executor
    auto parallel_fitnesses = executor.parallel_evaluate(tsp, population);

    // Results should be identical
    result.assert_eq(sequential_fitnesses.size(), parallel_fitnesses.size(),
                     "Fitness vector sizes should match");

    for (std::size_t i = 0; i < sequential_fitnesses.size(); ++i) {
        result.assert_true(sequential_fitnesses[i].value == parallel_fitnesses[i].value,
                           std::format("Parallel and sequential fitness should be identical {} "
                                       "(expected: {}, actual: {})",
                                       i, sequential_fitnesses[i].value,
                                       parallel_fitnesses[i].value));
    }

    result.print_summary();
    return result.all_passed();
}

[[nodiscard]] bool test_reproducibility_and_statelessness() {
    TestResult result;

    auto tsp = create_random_tsp(8, 100.0, 42);
    auto population = create_test_population(tsp, 100);

    // Multiple parallel runs with same seed should produce identical results
    TBBExecutor executor1;
    TBBExecutor executor2;

    auto fitnesses1 = executor1.parallel_evaluate(tsp, population);
    auto fitnesses2 = executor2.parallel_evaluate(tsp, population);

    result.assert_eq(fitnesses1.size(), fitnesses2.size(),
                     "Reproducibility: fitness vector sizes should match");

    for (std::size_t i = 0; i < fitnesses1.size(); ++i) {
        result.assert_true(
            fitnesses1[i].value == fitnesses2[i].value,
            std::format("Reproducibility: results should be identical for identical inputs {} "
                        "(expected: {}, actual: {})",
                        i, fitnesses1[i].value, fitnesses2[i].value));
    }

    // Regression test: stateless instance reuse verification
    // Tests that an executor instance maintains no mutable state between calls.
    // This would catch bugs where internal state gets corrupted during execution.
    // Distinct from fresh-instance tests below - different failure modes.
    auto fitnesses1_run2 = executor1.parallel_evaluate(tsp, population);

    result.assert_eq(fitnesses1.size(), fitnesses1_run2.size(),
                     "Statelessness: subsequent call result size must match");

    for (std::size_t i = 0; i < fitnesses1.size(); ++i) {
        result.assert_true(
            fitnesses1[i].value == fitnesses1_run2[i].value,
            std::format("Statelessness: subsequent call on same executor must be identical {} "
                        "(expected: {}, actual: {})",
                        i, fitnesses1[i].value, fitnesses1_run2[i].value));


#include "godotitch.h"
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/classes/json.hpp>
#include <godot_cpp/classes/project_settings.hpp>
#include <godot_cpp/classes/scene_tree.hpp>
#include <godot_cpp/classes/engine.hpp>
#include <godot_cpp/variant/utility_functions.hpp>

using namespace godot;

static Itch *s_singleton = nullptr;

void Itch::_bind_methods()
{
	// Itch.io API wrappers

	// Launch detection getters
	ClassDB::bind_method(D_METHOD("is_launched_via_itch"), &Itch::is_launched_via_itch);
	ClassDB::bind_method(D_METHOD("has_api_key_present"), &Itch::has_api_key_present);
	ClassDB::bind_method(D_METHOD("get_godotitch_version"), &Itch::get_godotitch_version);

	// Module access - expose all subsystems
	ClassDB::bind_method(D_METHOD("get_core"), &Itch::get_core);
	ClassDB::bind_method(D_METHOD("get_auth"), &Itch::get_auth);
	ClassDB::bind_method(D_METHOD("get_user"), &Itch::get_user);
	ClassDB::bind_method(D_METHOD("get_games"), &Itch::get_games);

	// Scene management
	ClassDB::bind_method(D_METHOD("initialize_with_scene", "scene_node"), &Itch::initialize_with_scene);

	// HTTP callback
	ClassDB::bind_method(D_METHOD("_on_request_completed", "result", "response_code", "headers", "body"), &Itch::_on_request_completed);
	// Internal helper to perform HTTP request deferred
	ClassDB::bind_method(D_METHOD("_perform_request", "url", "headers"), &Itch::_perform_request);
	ClassDB::bind_method(D_METHOD("post_request_check"), &Itch::post_request_check);

	// OAuth hooks (for integration to call after external flow)
	ClassDB::bind_method(D_METHOD("oauth_login_success", "user"), &Itch::oauth_login_success);
	ClassDB::bind_method(D_METHOD("oauth_login_failed", "error"), &Itch::oauth_login_failed);
	ClassDB::bind_method(D_METHOD("oauth_logged_out"), &Itch::oauth_logged_out);

	// OAuth helpers (delegated to Auth)
	ClassDB::bind_method(D_METHOD("set_oauth_client_id", "client_id"), &Itch::set_oauth_client_id);
	ClassDB::bind_method(D_METHOD("set_oauth_redirect_uri", "redirect_uri"), &Itch::set_oauth_redirect_uri);
	ClassDB::bind_method(D_METHOD("set_oauth_scope", "scope"), &Itch::set_oauth_scope);
	ClassDB::bind_method(D_METHOD("get_oauth_client_id"), &Itch::get_oauth_client_id);
	ClassDB::bind_method(D_METHOD("get_oauth_redirect_uri"), &Itch::get_oauth_redirect_uri);
	ClassDB::bind_method(D_METHOD("get_oauth_scope"), &Itch::get_oauth_scope);
	ClassDB::bind_method(D_METHOD("build_oauth_authorize_url", "client_id", "redirect_uri", "state"),
						 &Itch::build_oauth_authorize_url, DEFVAL(""), DEFVAL(""), DEFVAL(""));
	ClassDB::bind_method(D_METHOD("start_oauth_authorization", "client_id", "redirect_uri", "state"),
						 &Itch::start_oauth_authorization, DEFVAL(""), DEFVAL(""), DEFVAL(""));

	ClassDB::bind_method(D_METHOD("is_user_authenticated"), &Itch::is_user_authenticated);
	// ClassDB::bind_method(D_METHOD("get_current_user"), &Itch::get_current_user);
	// ClassDB::bind_method(D_METHOD("get_current_user_name"), &Itch::get_current_user_name);

	// Itch.io API methods
	ClassDB::bind_method(D_METHOD("get_credentials_info"), &Itch::get_credentials_info);
	ClassDB::bind_method(D_METHOD("get_me"), &Itch::get_me);

	// Signals
	ADD_SIGNAL(MethodInfo("api_response", PropertyInfo(Variant::STRING, "endpoint"),
						  PropertyInfo(Variant::DICTIONARY, "data")));
	ADD_SIGNAL(MethodInfo("api_error", PropertyInfo(Variant::STRING, "endpoint"),
	                      PropertyInfo(Variant::STRING, "error_message"),
	                      PropertyInfo(Variant::INT, "response_code")));

	// Auth signals
	ADD_SIGNAL(MethodInfo("user_logged_in", PropertyInfo(Variant::DICTIONARY, "user")));
	ADD_SIGNAL(MethodInfo("user_logged_out"));
	ADD_SIGNAL(MethodInfo("user_login_failed", PropertyInfo(Variant::STRING, "error")));
}

Itch::Itch()
{
	// Initialize modular architecture
	// Core and Auth are already initialized in register_types.cpp

	// Don't create HTTPRequest here - wait for initialize_with_scene()
	s_singleton = this;

	// Connect our own api_response signal to local handler
	connect("api_response", Callable(this, "_on_api_response"));
}

Itch::~Itch()
{
	if (http_request)
	{
		http_request->queue_free();
	}
	if (s_singleton == this)
	{
		s_singleton = nullptr;
	}
}

Itch *Itch::get_singleton()
{
	return s_singleton;
}

bool Itch::itchInitEx(uint32_t app_id, bool embed_callbacks)
{
	is_initialized = true;
	return true;
}

// Delegate launch detection to Auth submodule
void Itch::detect_launch_source()
{
	Auth::get_singleton()->do_detect_launch_source();
}

// Delegate authentication methods to Auth submodule
bool Itch::is_launched_via_itch() const
{
	return Auth::get_singleton()->is_launched_via_itch();
}

bool Itch::has_api_key_present() const
{
	return Auth::get_singleton()->has_api_key_present();
}

// Module access methods
Core *Itch::get_core() const
{
	return Core::get_singleton();
}

Auth *Itch::get_auth() const
{
	return Auth::get_singleton();
}

User *Itch::get_user() const
{
	return User::get_singleton


/* Copyright 2022-2023 John "topjohnwu" Wu
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

#include <cstdlib>
#include <unistd.h>
#include <fcntl.h>
#include <android/log.h>

#include "zygisk.hpp"

using zygisk::Api;
using zygisk::AppSpecializeArgs;
using zygisk::ServerSpecializeArgs;

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "MyModule", __VA_ARGS__)

class MyModule : public zygisk::ModuleBase {
public:
    void onLoad(Api *api, JNIEnv *env) override {
        this->api = api;
        this->env = env;
    }

    void preAppSpecialize(AppSpecializeArgs *args) override {
        // Use JNI to fetch our process name
        const char *process = env->GetStringUTFChars(args->nice_name, nullptr);
        preSpecialize(process);
        env->ReleaseStringUTFChars(args->nice_name, process);
    }

    void preServerSpecialize(ServerSpecializeArgs *args) override {
        preSpecialize("system_server");
    }

private:
    Api *api;
    JNIEnv *env;

    void preSpecialize(const char *process) {
        // Demonstrate connecting to to companion process
        // We ask the companion for a random number
        unsigned r = 0;
        int fd = api->connectCompanion();
        read(fd, &r, sizeof(r));
        close(fd);
        LOGD("process=[%s], r=[%u]\n", process, r);

        // Since we do not hook any functions, we should let Zygisk dlclose ourselves
        api->setOption(zygisk::Option::DLCLOSE_MODULE_LIBRARY);
    }

};

static int urandom = -1;

static void companion_handler(int i) {
    if (urandom < 0) {
        urandom = open("/dev/urandom", O_RDONLY);
    }
    unsigned r;
    read(urandom, &r, sizeof(r));
    LOGD("companion r=[%u]\n", r);
    write(i, &r, sizeof(r));
}

// Register our module class and the companion handler function
REGISTER_ZYGISK_MODULE(MyModule)
REGISTER_ZYGISK_COMPANION(companion_handler)


/*************************************************************************
 *** FORTE Library Element
 ***
 *** This file was generated using the 4DIAC FORTE Export Filter V1.0.x NG!
 ***
 *** Name: UDP_SEND_REAL_7
 *** Description: Service Interface Function Block Type
 *** Version:
 *** 1.0: 2025-08-09/arthu -  -
 *************************************************************************/

#include "UDP_SEND_REAL_7_fbt.h"
#ifdef FORTE_ENABLE_GENERATED_SOURCE_CPP
#include "ControlLoop/UDP_SEND_REAL_7_fbt_gen.cpp"
#endif

#include "iec61131_functions.h"
#include "forte_array_common.h"
#include "forte_array.h"
#include "forte_array_fixed.h"
#include "forte_array_variable.h"

// Fügen Sie die erforderlichen Standard-Bibliotheken hinzu
#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <unistd.h>
#include <sstream>
#include <arpa/inet.h>
#include <sys/socket.h>

#include <locale>
#include <codecvt>

DEFINE_FIRMWARE_FB(FORTE_ControlLoop__UDP_SEND_REAL_7, g_nStringIdControlLoop__UDP_SEND_REAL_7)

const CStringDictionary::TStringId FORTE_ControlLoop__UDP_SEND_REAL_7::scmDataInputNames[] = {g_nStringIdID, g_nStringIdIN1, g_nStringIdIN2, g_nStringIdIN3, g_nStringIdIN4, g_nStringIdIN5, g_nStringIdIN6, g_nStringIdIN7};
const CStringDictionary::TStringId FORTE_ControlLoop__UDP_SEND_REAL_7::scmDataInputTypeIds[] = {g_nStringIdWSTRING, g_nStringIdREAL, g_nStringIdREAL, g_nStringIdREAL, g_nStringIdREAL, g_nStringIdREAL, g_nStringIdREAL, g_nStringIdREAL};
const CStringDictionary::TStringId FORTE_ControlLoop__UDP_SEND_REAL_7::scmDataOutputNames[] = {g_nStringIdSTATUS};
const CStringDictionary::TStringId FORTE_ControlLoop__UDP_SEND_REAL_7::scmDataOutputTypeIds[] = {g_nStringIdWSTRING};
const TDataIOID FORTE_ControlLoop__UDP_SEND_REAL_7::scmEIWith[] = {0, scmWithListDelimiter, 1, 2, 3, 4, 5, 6, 7, scmWithListDelimiter};
const TForteInt16 FORTE_ControlLoop__UDP_SEND_REAL_7::scmEIWithIndexes[] = {0, 2};
const CStringDictionary::TStringId FORTE_ControlLoop__UDP_SEND_REAL_7::scmEventInputNames[] = {g_nStringIdINIT, g_nStringIdREQ};
const TDataIOID FORTE_ControlLoop__UDP_SEND_REAL_7::scmEOWith[] = {0, scmWithListDelimiter, 0, scmWithListDelimiter};
const TForteInt16 FORTE_ControlLoop__UDP_SEND_REAL_7::scmEOWithIndexes[] = {0, 2};
const CStringDictionary::TStringId FORTE_ControlLoop__UDP_SEND_REAL_7::scmEventOutputNames[] = {g_nStringIdINITO, g_nStringIdCNF};
const SFBInterfaceSpec FORTE_ControlLoop__UDP_SEND_REAL_7::scmFBInterfaceSpec = {
  2, scmEventInputNames, nullptr, scmEIWith, scmEIWithIndexes,
  2, scmEventOutputNames, nullptr, scmEOWith, scmEOWithIndexes,
  8, scmDataInputNames, scmDataInputTypeIds,
  1, scmDataOutputNames, scmDataOutputTypeIds,
  0, nullptr,
  0, nullptr
};

FORTE_ControlLoop__UDP_SEND_REAL_7::FORTE_ControlLoop__UDP_SEND_REAL_7(const CStringDictionary::TStringId paInstanceNameId, forte::core::CFBContainer &paContainer) :
    CFunctionBlock(paContainer, scmFBInterfaceSpec, paInstanceNameId),
    // Korrekte Initialisierung der Verbindungen hinzugefügt
    conn_INITO(this, 0),
    conn_CNF(this, 1),
    conn_STATUS(this, 0, &var_STATUS),
    var_ID(u""_WSTRING),
    var_IN1(0_REAL),
    var_IN2(0_REAL),
    var_IN3(0_REAL),
    var_IN4(0_REAL),
    var_IN5(0_REAL),
    var_IN6(0_REAL),
    var_IN7(0_REAL),
    var_STATUS(u""_WSTRING) {
};

// Korrekte Destruktor-Definition
FORTE_ControlLoop__UDP_SEND_REAL_7::~FORTE_ControlLoop__UDP_SEND_REAL_7() {
  if (m_udpSocket >= 0) {
    close(m_udpSocket);
  }
}

void FORTE_ControlLoop__UDP_SEND_REAL_7::setInitialValues() {
  var_ID = u""_WSTRING;
  var_IN1 = 0_REAL;
  var_IN2 = 0_REAL;
  var_IN3 = 0_REAL;
  var_IN4 = 0_REAL;
  var_IN5 = 0_REAL;
  var_IN6 = 0_REAL;
  var_IN7 = 0_REAL;
  var_STATUS = u""_WSTRING;
}

std::string wstring_to_string(const CIEC_WSTRING& wstr) {
  std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
  std::wstring ws = converter.from_bytes(wstr.getValue());
  std::string str(ws.begin(), ws.end());
  return str;
}

void FORTE_ControlLoop__UDP_SEND_REAL_7::executeEvent(const TEventID paEIID, CEventChainExecutionThread *const paECET) {
    switch(paEIID) {
        case scmEventINITID:
        {
            // 1. IP und Port aus der ID-Variable extrahieren
            // FORTE-WSTRING zu std::string konvertieren (korrigiert)
            std::string id_str = wstring_to_string(var_ID);
            size_t colon_pos = id_str.find(':');

            if (colon_pos == std::string::npos) {
                var_STATUS = u"Error: Invalid ID format. Expected 'ip:port'."_WSTRING;
                sendOutputEvent(scmEventINITOID, paECET);
                return;
            }

            std::string ip_str = id_str.substr(0, colon_pos);
            std::string port_str = id_str.substr(colon_pos + 1);

            int port = 0;
            std::istringstream iss(port_str);
            if (!(iss >> port)) {
                var_STATUS = u"Error: Invalid port number."_WSTRING;
                sendOutputEvent(scmEventINITO


#include <iostream>
#include <vector>
#include <unordered_map>

std::vector<int> twoSum(const std::vector<int>& nums, int target) {
    std::unordered_map<int, int> seen; // map: number → index

    for (int i = 0; i < nums.size(); ++i) {
        int complement = target - nums[i];

        // If complement is found in the map, return its index and current index
        if (seen.find(complement) != seen.end()) {
            return {seen[complement], i};
        }

        // Store the current number and its index
        seen[nums[i]] = i;
    }

    // No solution found (shouldn't happen per constraints)
    return {};
}

int main() {
    // Example 1
    std::vector<int> nums1 = {2, 7, 11, 15};
    int target1 = 9;

    // Example 2
    std::vector<int> nums2 = {3, 2, 4};
    int target2 = 6;

    // Example 3
    std::vector<int> nums3 = {3, 3};
    int target3 = 6;

    auto result1 = twoSum(nums1, target1);
    auto result2 = twoSum(nums2, target2);
    auto result3 = twoSum(nums3, target3);

    std::cout << "Example 1 Output: [" << result1[0] << ", " << result1[1] << "]\n";
    std::cout << "Example 2 Output: [" << result2[0] << ", " << result2[1] << "]\n";
    std::cout << "Example 3 Output: [" << result3[0] << ", " << result3[1] << "]\n";

    return 0;
}


#include "BPTextDumpModule.h" // MUST be first include
#include "BTD_Anchors.h"
#include "BTD_Hash.h"
#include "K2Node_Knot.h"          // 리루트(리라우트) 핀 추적
#include "EdGraph/EdGraphPin.h"

#include "Misc/EngineVersion.h"
#include "Misc/App.h"
#include "Interfaces/IPluginManager.h"
#include "ToolMenus.h"
#include "LevelEditor.h"
#include "ContentBrowserModule.h"
#include "BPTextDumpSettings.h"
#include "K2Node_CallFunction.h"
#include "K2Node_CustomEvent.h"
#include "K2Node_MacroInstance.h"
#include "K2Node_Variable.h"      // GetVarName()
#include "K2Node_Event.h"         // EventReference
#include "K2Node_VariableGet.h"
#include "K2Node_VariableSet.h"
#include "K2Node_FunctionEntry.h"
#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"
#include "Misc/Paths.h"
#include "Misc/FileHelper.h"
#include "HAL/FileManager.h"
#include "HAL/IConsoleManager.h"
#include "AssetRegistry/AssetRegistryModule.h"
#include "Engine/Blueprint.h"
#include "EdGraph/EdGraph.h"
#include "EdGraph/EdGraphNode.h"
#include "EdGraphSchema_K2.h"
#include "Json.h"
#include "JsonObjectConverter.h"
#include "ContentBrowserModule.h"      // for selection
#include "IContentBrowserSingleton.h"  // for selection
#include "UObject/UObjectGlobals.h" // for UObjectInitialized()
#include "Framework/Commands/UIAction.h" // ← FUIAction/FExecuteAction/FCanExecuteAction
// --- Components / SCS
#include "Engine/SimpleConstructionScript.h"
#include "Engine/SCS_Node.h"
#include "Components/PrimitiveComponent.h"
// --- Widgets / WidgetTree
#include "WidgetBlueprint.h"                 // UMGEditor 모듈
#include "Blueprint/UserWidget.h"
#include "Blueprint/WidgetTree.h"
#include "Components/PanelWidget.h"
#include "Components/PanelSlot.h"
#include "Components/CanvasPanelSlot.h"

//#include "Kismet2/BlueprintEditorUtils.h" // optional (for extra helpers)

IMPLEMENT_MODULE(FBPTextDumpModule, BPTextDump);

// 기존 파일 안의 정적 헬퍼들을 앞에서 참조할 수 있도록 프로토타입 추가
static bool WriteJsonToFile(const FJsonObject& Root, const FString& OutPath);
static bool WriteTextToFile(const FString& Text, const FString& OutPath);
static void AddFrontMatter(TSharedRef<FJsonObject> J);

// 우리가 쓰는 슬라이스 빌더 프로토타입
static void BuildSlicesForGraph(UEdGraph* Graph,
    const TArray<UEdGraphNode*>& SortedNodes,
    TArray<TSharedPtr<FJsonValue>>& Out);

static void BuildAndWriteSummaryForBP(
    UBlueprint* BP,
    const TArray<TSharedPtr<FJsonValue>>& Slices,
    const FString& MetaFilePath,
    const TArray<FString>& FlowJsonPaths,
    const FString& OutRoot);

static bool IsDataInputPin(const UEdGraphPin* P);
static FString GetCallTargetObjectVarName(const UK2Node_CallFunction * Call);
static FString GetObjectVarNameFromInputPin(UEdGraphPin* Pin);
static UEdGraphPin * FindInputPinByName(UEdGraphNode * N, const TCHAR * NameA, const TCHAR * NameB);

static TSharedPtr<FJsonObject> LoadJsonObject(const FString & Path)
 {
    FString JsonStr;
    if (!FFileHelper::LoadFileToString(JsonStr, *Path)) return nullptr;
    TSharedRef<TJsonReader<>> R = TJsonReaderFactory<>::Create(JsonStr);
    TSharedPtr<FJsonObject> Obj;
    FJsonSerializer::Deserialize(R, Obj);
    return Obj;
 }

// ============================================
// Project-Wide Reference Analysis: helpers
// ============================================
static FString ToAssetKeyFromClassPath(const FString& ClassPath)
{
    // "/Game/Path/Asset.Asset_C" -> "/Game/Path/Asset"
    // "/Script/Engine.Actor"     -> 그대로 유지
    if (ClassPath.StartsWith(TEXT("/Game/")))
    {
        int32 DotIdx = INDEX_NONE;
        if (ClassPath.FindChar(TCHAR('.'), DotIdx))
            return ClassPath.Left(DotIdx);
        return ClassPath;
    }
    if (ClassPath.StartsWith(TEXT("/Script/")))
    {
        return ClassPath;
    }
    return TEXT("");
}

static FString ToAssetKeyFromObjectPath(const FString& ObjPath)
{
    // UObject 경로는 보통 "/Game/A/B.Asset_C" 또는 "/Script/Module.Class"
    return ToAssetKeyFromClassPath(ObjPath);
}

static void AddRef(TMap<FString, TSet<FString>>& G, const FString& From, const FString& To)
{
    if (From.IsEmpty() || To.IsEmpty() || From == To) return;
    G.FindOrAdd(From).Add(To);
}

static void ReadNDJSONLines(const FString& Path, TFunctionRef<void(const TSharedPtr<FJsonObject>&)> Fn)
{
    FString Body;
    if (!FFileHelper::LoadFileToString(Body, *Path)) return;
    TArray<FString> Lines;
    Body.ParseIntoArrayLines(Lines);
    for (const FString& L : Lines)
    {
        if (L.TrimStartAndEnd().IsEmpty()) continue;
        TSharedRef<TJsonReader<>> R = TJsonReaderFactory<>::Create(L);
        TSharedPtr<FJsonObject> O;
        if (FJsonSerializer::Deserialize(R, O) && O.IsValid())
            Fn(O);
    }
}

// ============================================================
// Phase 6.5 — Source & Origin Analysis helpers
// ============================================================
static FString GetSelfClassPath(UBlueprint* BP)
{
    if (!BP) return TEXT("");
    if (BP->GeneratedClass) return BP->


/* Leetcode problem: Apply Operations to an Array

You are given a 0-indexed array nums of size n consisting of non-negative integers.

You need to apply n - 1 operations to this array where, in the ith operation (0-indexed), you will apply the following on the ith element of nums:

If nums[i] == nums[i + 1], then multiply nums[i] by 2 and set nums[i + 1] to 0. Otherwise, you skip this operation.
After performing all the operations, shift all the 0's to the end of the array.

For example, the array [1,0,2,0,0,1] after shifting all its 0's to the end, is [1,2,1,0,0,0].
Return the resulting array.

Note that the operations are applied sequentially, not all at once.

Example 1:

Input: nums = [1,2,2,1,1,0]
Output: [1,4,2,0,0,0]
Explanation: We do the following operations:
- i = 0: nums[0] and nums[1] are not equal, so we skip this operation.
- i = 1: nums[1] and nums[2] are equal, we multiply nums[1] by 2 and change nums[2] to 0. The array becomes [1,4,0,1,1,0].
- i = 2: nums[2] and nums[3] are not equal, so we skip this operation.
- i = 3: nums[3] and nums[4] are equal, we multiply nums[3] by 2 and change nums[4] to 0. The array becomes [1,4,0,2,0,0].
- i = 4: nums[4] and nums[5] are equal, we multiply nums[4] by 2 and change nums[5] to 0. The array becomes [1,4,0,2,0,0].
After that, we shift the 0's to the end, which gives the array [1,4,2,0,0,0].
*/

// Solution
#include<vector>
using namespace std;
class Solution {
public:
    vector<int> applyOperations(vector<int>& nums) {
        int n = nums.size();
        for(int i = 0; i < n - 1; i++) {
            if(nums[i] == nums[i + 1]) {
                nums[i] *= 2;
                nums[i + 1] = 0;
            }
        }
        vector<int> result(n);
        int index = 0;
        for(int i = 0; i < n; i++) {
            if(nums[i] != 0) {
                result[index++] = nums[i];
            }
        }
        return result;
    }
};


// algparam.cpp - originally written and placed in the public domain by Wei Dai

#include "pch.h"

#ifndef CRYPTOPP_IMPORTS

#include "algparam.h"
#include "integer.h"

NAMESPACE_BEGIN(CryptoPP)

bool CombinedNameValuePairs::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{
	if (strcmp(name, "ValueNames") == 0)
		return m_pairs1.GetVoidValue(name, valueType, pValue) && m_pairs2.GetVoidValue(name, valueType, pValue);
	else
		return m_pairs1.GetVoidValue(name, valueType, pValue) || m_pairs2.GetVoidValue(name, valueType, pValue);
}

void AlgorithmParametersBase::operator=(const AlgorithmParametersBase &rhs)
{
	CRYPTOPP_UNUSED(rhs);
	CRYPTOPP_ASSERT(false);
}

bool AlgorithmParametersBase::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{
	if (strcmp(name, "ValueNames") == 0)
	{
		NameValuePairs::ThrowIfTypeMismatch(name, typeid(std::string), valueType);
		if (m_next.get())
		    m_next->GetVoidValue(name, valueType, pValue);
		(*reinterpret_cast<std::string *>(pValue) += m_name) += ";";
		return true;
	}
	else if (strcmp(name, m_name) == 0)
	{
		AssignValue(name, valueType, pValue);
		m_used = true;
		return true;
	}
	else if (m_next.get())
		return m_next->GetVoidValue(name, valueType, pValue);
	else
	    return false;
}

AlgorithmParameters::AlgorithmParameters()
	: m_defaultThrowIfNotUsed(true)
{
}

AlgorithmParameters::AlgorithmParameters(const AlgorithmParameters &x)
	: m_defaultThrowIfNotUsed(x.m_defaultThrowIfNotUsed)
{
	m_next.reset(const_cast<AlgorithmParameters &>(x).m_next.release());
}

AlgorithmParameters & AlgorithmParameters::operator=(const AlgorithmParameters &x)
{
	m_next.reset(const_cast<AlgorithmParameters &>(x).m_next.release());
	return *this;
}

bool AlgorithmParameters::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{
	if (m_next.get())
		return m_next->GetVoidValue(name, valueType, pValue);
	else
		return false;
}

NAMESPACE_END

#endif


/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   main.cpp                                           :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: ylabser <ylabser@student.42.fr>            +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2025/08/25 19:04:46 by ylabser           #+#    #+#             */
/*   Updated: 2025/08/25 19:04:46 by ylabser          ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include "PhoneBook.hpp"
#include <iostream>
#include <sstream>

std::string promptNonEmpty(const std::string& message)
{
   std::string input;
   while (true)
   {
      std::cout << message;
      std::getline(std::cin, input);
      if (!input.empty())
         return input;
      std::cout << "Empty line." << std::endl;
   }
}

Contact createContact()
{
   std::string firstName, lastName, nickName, phoneNumber, darkestSecret;

   firstName = promptNonEmpty("First name: ");
   lastName = promptNonEmpty("Last name: ");
   nickName = promptNonEmpty("Nickname: ");
   phoneNumber = promptNonEmpty("Phone Number: ");
   darkestSecret = promptNonEmpty("Darkest secret: ");

   Contact contact;
   contact.setContact(firstName, lastName, nickName, phoneNumber, darkestSecret);

   return contact;
}

int main ()
{
   PhoneBook phoneBook;
   std::string command;

   while (true)
   {
      std::cout << "Enter command (ADD, SEARCH, EXIT): ";
      std::getline(std::cin, command);
      if (command == "ADD")
      {
         Contact contact = createContact();
         phoneBook.addContact(contact);
      }
      else if (command == "SEARCH")
      {
         phoneBook.displayContacts();
         if (phoneBook.getCount() > 0)
         {
            std::cout << "Enter index for details: ";
            std::string indexStr;
            std::getline(std::cin, indexStr);
            int index;
            std::istringstream iss(indexStr);
            if (!(iss >> index)) {
               std::cout << "Index invalide." << std::endl;
               continue;
            }
            phoneBook.displayContactDetails(index);
         }
      }
      else if (command == "EXIT")
         break;
      else
         std::cout << "Unknown command." << std::endl;
   }
   return 0;
}


/* Rotary encoder handler for arduino.
 *
 * Copyright 2011 Ben Buxton. Licenced under the GNU GPL Version 3.
 * Contact: bb@cactii.net
 *
 */

#include "Arduino.h"
#include "Rotary.h"

/*
 * The below state table has, for each state (row), the new state
 * to set based on the next encoder output. From left to right in,
 * the table, the encoder outputs are 00, 01, 10, 11, and the value
 * in that position is the new state to set.
 */

#define R_START 0x0

#ifdef HALF_STEP
// Use the half-step state table (emits a code at 00 and 11)
#define R_CCW_BEGIN 0x1
#define R_CW_BEGIN 0x2
#define R_START_M 0x3
#define R_CW_BEGIN_M 0x4
#define R_CCW_BEGIN_M 0x5
const unsigned char ttable[6][4] = {
  // R_START (00)
  {R_START_M,            R_CW_BEGIN,     R_CCW_BEGIN,  R_START},
  // R_CCW_BEGIN
  {R_START_M | DIR_CCW, R_START,        R_CCW_BEGIN,  R_START},
  // R_CW_BEGIN
  {R_START_M | DIR_CW,  R_CW_BEGIN,     R_START,      R_START},
  // R_START_M (11)
  {R_START_M,            R_CCW_BEGIN_M,  R_CW_BEGIN_M, R_START},
  // R_CW_BEGIN_M
  {R_START_M,            R_START_M,      R_CW_BEGIN_M, R_START | DIR_CW},
  // R_CCW_BEGIN_M
  {R_START_M,            R_CCW_BEGIN_M,  R_START_M,    R_START | DIR_CCW},
};
#else
// Use the full-step state table (emits a code at 00 only)
#define R_CW_FINAL 0x1
#define R_CW_BEGIN 0x2
#define R_CW_NEXT 0x3
#define R_CCW_BEGIN 0x4
#define R_CCW_FINAL 0x5
#define R_CCW_NEXT 0x6

const unsigned char ttable[7][4] = {
  // R_START
  {R_START,    R_CW_BEGIN,  R_CCW_BEGIN, R_START},
  // R_CW_FINAL
  {R_CW_NEXT,  R_START,     R_CW_FINAL,  R_START | DIR_CW},
  // R_CW_BEGIN
  {R_CW_NEXT,  R_CW_BEGIN,  R_START,     R_START},
  // R_CW_NEXT
  {R_CW_NEXT,  R_CW_BEGIN,  R_CW_FINAL,  R_START},
  // R_CCW_BEGIN
  {R_CCW_NEXT, R_START,     R_CCW_BEGIN, R_START},
  // R_CCW_FINAL
  {R_CCW_NEXT, R_CCW_FINAL, R_START,     R_START | DIR_CCW},
  // R_CCW_NEXT
  {R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START},
};
#endif

/*
 * Constructor. Each arg is the pin number for each encoder contact.
 */
Rotary::Rotary(char _pin1, char _pin2) {
  // Assign variables.
  pin1 = _pin1;
  pin2 = _pin2;
  // Initialise state.
  state = R_START;
}

void Rotary::begin(bool pullup) {

  if (pullup){
    // Enable weak pullups
    pinMode(pin1,INPUT_PULLUP);
    pinMode(pin2,INPUT_PULLUP);
  }else{
    // Set pins to input.
    pinMode(pin1, INPUT);
    pinMode(pin2, INPUT);
  }
}

unsigned char Rotary::process() {
	return process(digitalRead(pin1), digitalRead(pin2));
}

unsigned char Rotary::process(unsigned char pin1State, unsigned char pin2State) {
	  // Grab state of input pins.
	  unsigned char pinstate = (pin2State << 1) | pin1State;
	  // Determine new state from the pins and state table.
	  state = ttable[state & 0xf][pinstate];
	  // Return emit bits, ie the generated event.
	  return state & 0x30;
}


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

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

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

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

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

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

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

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

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

  ::CoUninitialize();
  return EXIT_SUCCESS;
}


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

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

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

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

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

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

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

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

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

  ::CoUninitialize();
  return EXIT_SUCCESS;
}


#include <iostream>
#include <limits>
#include "hash_table.hpp"
#include "avl_tree.hpp"
#include "bst.hpp"
#include "delivery_graph.hpp"
using namespace std;

// struct Warehouse
// {
//   string nama;
//   vector<pair<int, int>> neighbors;
//   Warehouse(string nama, vector<pair<int, int>> neighbors) : nama(nama), neighbors(neighbors) {}
// };

void menuProduk(HashTable &lookup, AVLTree &avl)
{
  int pilihan;
  do
  {
    cout << "\n=== MENU PRODUK ===\n";
    cout << "1. Tambah Produk\n";
    cout << "2. Cari Produk\n";
    cout << "3. Hapus Produk\n";
    cout << "4. Tampilkan Semua Produk\n";
    cout << "5. Tampilkan semua produk By nama\n";
    cout << "6. Simpan ke CSV\n";
    cout << "7. Kembali ke Menu Utama\n";
    cout << "Pilih: ";
    cin >> pilihan;

    if (cin.fail())
    {
      cin.clear();
      cin.ignore(numeric_limits<streamsize>::max(), '\n');
      cout << "Input tidak valid. Harap masukkan angka.\n";
      continue;
    }

    switch (pilihan)
    {
    case 1:
    {
      int id, stok, sales;
      double harga, rating;
      string nama;
      cout << "ID: ";
      cin >> id;
      if (lookup.search(id))
      {
        cout << "Produk dengan ID tersebut sudah ada.\n";
        break;
      }
      cin.ignore(numeric_limits<streamsize>::max(), '\n');

      cout << "Nama: ";
      getline(cin, nama);
      cout << "Harga: ";
      cin >> harga;
      cout << "Stok: ";
      cin >> stok;
      cout << "Sales: ";
      cin >> sales;
      cout << "Rating: ";
      cin >> rating;
      Produk p(id, nama, harga, stok, sales, rating);
      lookup.insert(p);
      avl.insert(p);
    }
    break;
    case 2:
    {
      int id;
      cout << "Masukkan id produk yang ingin dicari: ";
      cin >> id;
      Produk *p = lookup.search(id);
      if (p)
        cout
            << "Ditemukan: " << p->namaProduk << ", Harga: " << p->hargaProduk << "\n";
      else
        cout << "Produk tidak ditemukan.\n";
    }
    break;
    case 3:
    {
      int id;
      cout << "Masukkan id produk yang ingin dihapus: ";
      cin >> id;
      lookup.remove(id);
      cout << "Produk dihapus dari hash table (AVL tidak dihapus).\n";
    }
    break;
    case 4:
    {
      lookup.printAll();
    }
    break;
    case 5:
    {
      lookup.listByNama();
    }
    break;
    case 6:
    {
      lookup.saveToCsv("produk");
      avl.saveToCSV("riwayatProduk");
    }
    break;

    default:
      system("cls");
      break;
    }
  } while (pilihan != 7);
}

void menuRiwayat(AVLTree &avl)
{
  cout << "\n=== Riwayat Produk (Harga - Inorder) ===\n";
  avl.displayInOrder();
}

void menuPemesanan(OrderBst &orders)
{

  int pilihan;
  do
  {
    cout << "\n=== MENU PEMESANAN ===\n";
    cout << "1. Tambah Order\n"
         << "2. Tampilkan Riwayat Order\n"
         << "3. Simpan Riwayat order\n"
         << "4. Kembali ke Menu Utama\n";
    cout << "Pilihan: ";
    cin >> pilihan;

    switch (pilihan)
    {
    case 1:
    {
      int orderId, produkId, qty;
      string date;
      cout << "ID Order: ";
      cin >> orderId;
      cout << "ID Produk: ";
      cin >> produkId;
      cin.ignore();
      cout << "Tanggal (YYYY-MM-DD): ";
      getline(cin, date);
      cout << "Jumlah: ";
      cin >> qty;
      orders.insert(Order(orderId, produkId, date, qty));
    }
    break;
    case 2:

      orders.displayRiwayat();
      break;
    case 3:
      orders.saveToCsv("order");
      break;
    default:
      system("cls");
      break;
    }
  } while (pilihan != 4);
}

void menuPengiriman(DeliveryGraph &graph)
{
  int pilihan;
  string dari, ke;
  double jarak;
  do
  {
    cout << "\n=== MENU PENGIRIMAN ===\n";
    cout << "1. Tambah Rute\n";
    cout << "2. Lihat Rute (BFS)\n";
    cout << "3. Lihat Rute (DFS)\n";
    cout << "4. Lihat semua rute\n";
    cout << "5. Simpan Semua Rute\n";
    cout << "6. Kembali ke Menu Utama\n";
    cout << "Pilih: ";
    cin >> pilihan;

    switch (pilihan)
    {
    case 1:
    {
      cout << "Dari: ";
      cin >> dari;
      cout << "Ke: ";
      cin >> ke;
      cout << "Jarak dalam KM: ";
      cin >> jarak;
      graph.addEdge(dari, ke, jarak);
    }
    break;
    case 2:
    {
      cout << "Mulai dari: ";
      cin >> dari;
      graph.bfs(dari);
    }
    break;
    case 3:
    {
      cout << "Mulai dari: ";
      cin >> dari;
      graph.dfs(dari);
    }
    break;
    case 4:
      graph.displayRoutes();
      break;
    case 5:
      graph.saveToCsv("rute");
      break;
    default:
      system("cls");
      break;
    }
  } while (pilihan != 6);
}
int main()
{
  HashTable lookup;
  AVLTree riwayatProduk;
  OrderBst orderTree;
  DeliveryGraph pengiriman;

  // Muat dari CSV jika ada
  lookup.loadFromCsv("produk");
  orderTree.loadFile("order");
  riwayatProduk.loadFromCSV("riwayatProduk");
  pengiriman.loadFromCsv("rute");
  int pilihan;
  do
  {
    cout << "\n=== SISTEM E-COMMERCE ===\n";
    cout << "1. Kelola Produk\n";
    cout << "2. Lihat Riwayat


#include<iostream>
using namespace std;

#define tab "\t"

class Tree
{
	class Element
	{
		int Data;
		Element* pLeft;
		Element* pRight;
	public:
		Element(int Data, Element* pLeft = nullptr, Element* pRight = nullptr) :
			Data(Data), pLeft(pLeft), pRight(pRight)
		{
			cout << "EConstructor:\t" << this << endl;
		}
		~Element()
		{
			cout << "EDestructor:\t" << this << endl;
		}
		friend class Tree;
	}*Root;
public:
	Element* getRoot()const
	{
		return Root;
	}
	Tree() :Root(nullptr)
	{
		cout << "TConstructor:\t" << this << endl;
	}
	~Tree()
	{
		cout << "TDestructor:\t" << this << endl;
	}
	void insert(int Data, Element* Root)
	{
		if (this->Root == nullptr) this->Root = new Element(Data);
		if (Root == nullptr)return;
		if (Data < Root->Data)
		{
			if (Root->pLeft == nullptr)Root->pLeft = new Element(Data);
			else insert(Data, Root->pLeft);
		}
		else
		{
			if (Root->pRight == nullptr)Root->pRight = new Element(Data);
			else insert(Data, Root->pRight);
		}
	}
	int minValue(Element* Root)
	{
	/*	if (Root->pLeft == nullptr)return Root->Data;
		else return minValue(Root->pLeft);*/
		return Root == nullptr ? INT_MIN : Root->pLeft == nullptr ? Root->Data : minValue(Root->pLeft);
	}
	int maxValue(Element* Root)
	{
		/*if (Root->pRight == nullptr) return Root->Data;
		else return maxValue(Root->pRight);*/
		return !Root ? INT_MIN : Root->pRight ? maxValue(Root->pRight) : Root->Data;
	}
	int count(Element* Root)
	{
		/*if (Root == nullptr)return 0;
		else return count(Root->pLeft) + count(Root->pRight) + 1;*/
		//return Root == nullptr ? 0 : count(Root->pLeft) + count(Root->pRight) + 1;
		return !Root ? 0 : count(Root->pLeft) + count(Root->pRight) + 1;
	}
	void print(Element* Root)const
	{
		if (Root == nullptr)return;
		print(Root->pLeft);
		cout << Root->Data << tab;
		print(Root->pRight);
	}
};

void main()
{
	setlocale(LC_ALL, "");
	//cout << "Hello Tree" << endl;
	int n;
	cout << "Введите количество элементов: "; cin >> n;
	Tree tree;
	for (int i = 0; i < n; i++)
	{
		tree.insert(rand() % 100, tree.getRoot());
	}
	tree.print(tree.getRoot());
	cout << endl;
	cout << "Минимальное значение в дереве: " << tree.minValue(tree.getRoot()) << endl;
	cout << "Максимальное значение в дереве: " << tree.maxValue(tree.getRoot()) << endl;
	cout << "Количество элементов дерева: " << tree.count(tree.getRoot()) << endl;
}


#include "translate.h"

#include <string_view>

Translate::Translate(QObject* parent) : QObject(parent) {}

Translate::~Translate() {}

void Translate::Transliterate(Language lang) {
  auto transliterate = [this, lang](std::string_view view_text) -> std::string {
    std::string result;
    for (size_t i = 0; i < view_text.size();) {
      bool found = false;
      switch (lang) {
        case Language::TRANSLIT: {
          for (const auto& [key, value] : data_.transliteration_map) {
            if (i + key.size() <= view_text.size() && view_text.substr(i, key.size()) == key) {
              result += value;
              i += key.size();
              found = true;
              break;
            }
          }
          break;
        }
        case Language::TO_RUSSIAN: {
          for (const auto& [key, value] : data_.eng_transliteration_map) {
            if (i + key.size() <= view_text.size() && view_text.substr(i, key.size()) == key) {
              result += value;
              i += key.size();
              found = true;
              break;
            }
          }
          break;
        }
        case Language::TO_ENGLISH: {
          for (const auto& [key, value] : data_.rus_transliteration_map) {
            if (i + key.size() <= view_text.size() && view_text.substr(i, key.size()) == key) {
              result += value;
              i += key.size();
              found = true;
              break;
            }
          }
          break;
        }
      };

      if (!found) {
        result += view_text[i];
        ++i;
      }
    }
    return result;
  };

  result_text_ = transliterate(query_text_);
}