#include <iostream>
#include <string>
#include <sstream>
#include <cctype>
#include "../Integer.h"

// Simple CLI to exercise UnsignedInteger and SignedInteger
// Protocol (per line, whitespace separated):
//   <type> <op> <a> [b]
// where:
//   <type>: U | S   (UnsignedInteger or SignedInteger)
//   <op>: add sub mul div mod cmp to_str to_u64 to_s64 to_double
//   <a>, <b>: base-10 integer strings (for S may start with '-')
// Output:
//   On success:  "OK <result>" (result is decimal string or scalar)
//   On exception: "EXC <what>"

static inline void trim(std::string &s) {
    size_t p = 0; while (p < s.size() && std::isspace(static_cast<unsigned char>(s[p]))) ++p; s.erase(0, p);
    while (!s.empty() && std::isspace(static_cast<unsigned char>(s.back()))) s.pop_back();
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    std::string line;
    while (std::getline(std::cin, line)) {
        trim(line);
        if (line.empty()) continue;
        std::istringstream iss(line);
        std::string type, op, a, b;
        iss >> type >> op >> a;
        if (type.empty() || op.empty() || a.empty()) {
            std::cout << "EXC invalid input" << '\n';
            continue;
        }
        if (op == "add" || op == "sub" || op == "mul" || op == "div" || op == "mod" || op == "cmp") {
            if (!(iss >> b)) { std::cout << "EXC missing operand" << '\n'; continue; }
        }
        try {
            if (type == "U") {
                if (op == "to_str") {
                    UnsignedInteger ua(a.c_str());
                    std::cout << "OK " << ua << '\n';
                } else if (op == "to_u64") {
                    UnsignedInteger ua(a.c_str());
                    unsigned long long v = static_cast<unsigned long long>(ua);
                    std::cout << "OK " << v << '\n';
                } else if (op == "to_double") {
                    UnsignedInteger ua(a.c_str());
                    double v = static_cast<double>(ua);
                    std::ostringstream os; os.setf(std::ios::fixed); os.precision(0); os << v; // no frac
                    std::cout << "OK " << os.str() << '\n';
                } else if (op == "add" || op == "sub" || op == "mul" || op == "div" || op == "mod") {
                    UnsignedInteger ua(a.c_str());
                    UnsignedInteger ub(b.c_str());
                    if (op == "add") {
                        auto r = ua + ub;
                        std::cout << "OK " << r << '\n';
                    } else if (op == "sub") {
                        auto r = ua - ub; // may throw if ua < ub
                        std::cout << "OK " << r << '\n';
                    } else if (op == "mul") {
                        auto r = ua * ub;
                        std::cout << "OK " << r << '\n';
                    } else if (op == "div") {
                        auto r = ua / ub; // may throw if ub == 0
                        std::cout << "OK " << r << '\n';
                    } else { // mod
                        auto r = ua % ub; // may throw if ub == 0
                        std::cout << "OK " << r << '\n';
                    }
                } else if (op == "cmp") {
                    UnsignedInteger ua(a.c_str());
                    UnsignedInteger ub(b.c_str());
                    int sgn = (ua < ub) ? -1 : (ua == ub ? 0 : 1);
                    std::cout << "OK " << sgn << '\n';
                } else {
                    std::cout << "EXC unknown op" << '\n';
                }
            } else if (type == "S") {
                if (op == "to_str") {
                    SignedInteger sa(a.c_str());
                    std::cout << "OK " << sa << '\n';
                } else if (op == "to_s64") {
                    SignedInteger sa(a.c_str());
                    long long v = static_cast<long long>(sa);
                    std::cout << "OK " << v << '\n';
                } else if (op == "to_u64") {
                    SignedInteger sa(a.c_str());
                    unsigned long long v = static_cast<unsigned long long>(sa); // may throw if negative
                    std::cout << "OK " << v << '\n';
                } else if (op == "to_double") {
                    SignedInteger sa(a.c_str());
                    double v = static_cast<double>(sa);
                    std::ostringstream os; os.setf(std::ios::fixed); os.precision(0); os << v; // no frac
                    std::cout << "OK " << os.str() << '\n';
                } else if (op == "add" || op == "sub" || op == "mul" || op == "div" || op == "mod") {
                    SignedInteger sa(a.c_str());
                    SignedInteger sb(b.c_str());
                    if (op == "add") {
                        auto r = sa + sb;
                        std::cout << "OK " << r << '\n';
                    } else if (op == "sub") {
                        auto r = sa - sb;
                        std::cout << "OK " << r << '\n';


#include "HanoiGame.h"
#include "TowerSolver.h"
#include <SFML/Audio.hpp>
#include <thread>
#include <chrono>
#include <iostream>

// конструктор гри
HanoiGame::HanoiGame(int numDisks)
    : diskCount(numDisks), userMoves(0), isSolving(false), solveMoveIndex(0),
    movingDisk(nullptr), baseY(0), diskHeight(0), rodWidth(0),
    fromPeg(-1), gameWon(false), shouldReturnToMenu(false) {}

// ініціалізує гру - створює основу, стрижні, диски та кнопки
void HanoiGame::initGame(sf::Vector2u winSize)
{
    float winW = static_cast<float>(winSize.x);
    float winH = static_cast<float>(winSize.y);

    // фон
    if (backgroundTexture.loadFromFile("background.jpg"))
    {
        backgroundSprite.setTexture(backgroundTexture);
        backgroundSprite.setScale(
            winW / backgroundTexture.getSize().x,
            winH / backgroundTexture.getSize().y );
    }

    // основа гри
    base.setSize(sf::Vector2f(600.f, 50.f));
    base.setFillColor(sf::Color(139, 69, 19));
    base.setOrigin(base.getSize().x / 2.f, base.getSize().y / 2.f);
    base.setPosition(winW / 2.f, winH - 40.f);
    baseY = base.getPosition().y;

    // створення трьох стрижнів
    float rodHeight = 200.f;
    rodWidth = 10.f;
    float xSpacing = 200.f;
    float startX = winW / 2.f - xSpacing;
    sf::Color rodColor(160, 82, 45);

    for (int i = 0; i < 3; ++i)
        pegs[i] = Peg(startX + i * xSpacing, baseY, rodHeight, rodWidth, rodColor);

    // створення дисків
    diskHeight = 20.f;
    float maxW = 160.f;
    float minW = 60.f;
    disks.clear();

    for (int i = diskCount; i >= 1; --i)
    {
        float width = minW + (i - 1) * (maxW - minW) / (diskCount - 1);
        sf::Color color = sf::Color(100 + 15 * i, 100 + 10 * i, 255 - 10 * i);
        Disk* d = new Disk(i, width, diskHeight, color);
        d->shape.setPosition(pegs[0].x, baseY - pegs[0].getDisks().size() * diskHeight);
        pegs[0].pushDisk(d);
        disks.push_back(d);
    }

   // створення кнопки Solve
    solveButton.setSize(sf::Vector2f(120.f, 50.f)); // розміри кнопки
    solveButton.setFillColor(sf::Color::White); // білий фон
    solveButton.setOutlineThickness(4.f); // товщина обводки
    solveButton.setOutlineColor(sf::Color(81, 147, 159)); // голуба обводка

    // отримання розміру вікна для позиціювання
    sf::Vector2u windowSize = winSize;

    // розміщення кнопки в правому верхньому куті з відступом 20 пікселів
    solveButton.setPosition( windowSize.x - solveButton.getSize().x - 20.f, 20.f );

    // створення кнопки Restart
    restartButton.setSize(sf::Vector2f(120.f, 50.f)); // розміри кнопки
    restartButton.setFillColor(sf::Color::White); // білий фон
    restartButton.setOutlineThickness(4.f); // товщина обводки
    restartButton.setOutlineColor(sf::Color(81, 147, 159)); // голуба обводка

    // розміщення кнопки лівіше від Solve
    restartButton.setPosition(
        solveButton.getPosition().x - restartButton.getSize().x - 15.f,
        solveButton.getPosition().y );

    // тексти
    if (font.loadFromFile("MyFont.ttf"))
    {
        solveText.setFont(font);
        solveText.setString("Solve");
        solveText.setCharacterSize(30);
        solveText.setFillColor(sf::Color::Black);
        solveText.setPosition(solveButton.getPosition().x + 15.f, solveButton.getPosition().y + 5.f);

        movesText.setFont(font);
        movesText.setCharacterSize(35);
        movesText.setFillColor(sf::Color::Black);
        movesText.setPosition(20.f, 20.f);
        movesText.setString("Moves: 0");

        restartText.setFont(font);
        restartText.setCharacterSize(30);
        restartText.setFillColor(sf::Color::Black);
        restartText.setPosition(restartButton.getPosition().x + 15.f, restartButton.getPosition().y + 5.f);
        restartText.setString("Restart");
    }
}

// обробка подій миші
void HanoiGame::handleEvents(sf::RenderWindow& window)
{
    sf::Event event;
    while (window.pollEvent(event))
    {
        if (event.type == sf::Event::Closed) window.close();

        if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left)
        {
            float mx = static_cast<float>(event.mouseButton.x);
            float my = static_cast<float>(event.mouseButton.y);

            if (solveButton.getGlobalBounds().contains(mx, my))
            {
                resetToInitialState();
                TowerSolver::solveHanoi(diskCount, 0, 2, 1, solveMoves);
                isSolving = true;
                solveMoveIndex = 0;
            }

            else if (restartButton.getGlobalBounds().contains(mx, my))
            {
                shouldReturnToMenu = true; // повернення до меню
            }

            else
            {
                for (int i = 0; i < 3; ++i)
                {
                    if (!pegs[i].getDis


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

#define LOG_TAG "uprobestats"

#include <BpfSyscallWrappers.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <linux/perf_event.h>

#include <string>

#include "bpf/BpfMap.h"
#include "bpf/BpfRingbuf.h"

#include "Bpf.h"

namespace android {
namespace uprobestats {
namespace bpf {

const char *PMU_TYPE_FILE = "/sys/bus/event_source/devices/uprobe/type";

int bpfPerfEventOpen(const char *filename, int offset, int pid,
                     const char *bpfProgramPath) {
  android::base::unique_fd bpfProgramFd(
      android::bpf::retrieveProgram(bpfProgramPath));
  if (bpfProgramFd < 0) {
    LOG(ERROR) << "retrieveProgram failed";
    return -1;
  }

  std::string typeStr;
  if (!android::base::ReadFileToString(PMU_TYPE_FILE, &typeStr)) {
    LOG(ERROR) << "Failed to open pmu type file";
    return -1;
  }
  int pmu_type = (int)strtol(typeStr.c_str(), NULL, 10);

  struct perf_event_attr attr = {};
  attr.sample_period = 1;
  attr.wakeup_events = 1;
  attr.config2 = offset;
  attr.size = sizeof(attr);
  attr.type = pmu_type;
  attr.config1 = android::bpf::ptr_to_u64((void *)filename);
  attr.exclude_kernel = true;

  int perfEventFd = syscall(__NR_perf_event_open, &attr, pid, /*cpu=*/-1,
                            /* group_fd=*/-1, PERF_FLAG_FD_CLOEXEC);
  if (perfEventFd < 0) {
    LOG(ERROR) << "syscall(__NR_perf_event_open) failed. "
               << "perfEventFd: " << perfEventFd << " "
               << "error: " << strerror(errno);
    return -1;
  }
  if (ioctl(perfEventFd, PERF_EVENT_IOC_SET_BPF, int(bpfProgramFd)) < 0) {
    LOG(ERROR) << "PERF_EVENT_IOC_SET_BPF failed. " << strerror(errno);
    return -1;
  }
  if (ioctl(perfEventFd, PERF_EVENT_IOC_ENABLE, 0) < 0) {
    LOG(ERROR) << "PERF_EVENT_IOC_ENABLE failed. " << strerror(errno);
    return -1;
  }
  return 0;
}

template <typename T>
std::vector<T> pollRingBuf(const char *mapPath, int timeoutMs) {
  auto result = android::bpf::BpfRingbuf<T>::Create(mapPath);
  std::vector<T> vec;
  if (!result.value()->wait(timeoutMs)) {
    return vec;
  }
  auto callback = [&](const T &value) { vec.push_back(value); };
  result.value()->ConsumeAll(callback);
  return vec;
}

template std::vector<uint64_t> pollRingBuf(const char *mapPath, int timeoutMs);
template std::vector<CallResult> pollRingBuf(const char *mapPath,
                                             int timeoutMs);
template std::vector<CallTimestamp> pollRingBuf(const char *mapPath,
                                                int timeoutMs);
template std::vector<SetUidTempAllowlistStateRecord>
pollRingBuf(const char *mapPath, int timeoutMs);

template std::vector<UpdateDeviceIdleTempAllowlistRecord>
pollRingBuf(const char *mapPath, int timeoutMs);

template std::vector<MalwareSignal> pollRingBuf(const char *mapPath,
                                                int timeoutMs);

std::vector<int32_t> consumeRingBuf(const char *mapPath) {
  auto result = android::bpf::BpfRingbuf<uint64_t>::Create(mapPath);
  std::vector<int32_t> vec;
  auto callback = [&](const uint64_t &value) { vec.push_back(value); };
  result.value()->ConsumeAll(callback);
  return vec;
}

void printRingBuf(const char *mapPath) {
  auto result = android::bpf::BpfRingbuf<uint64_t>::Create(mapPath);
  auto callback = [&](const uint64_t &value) {
    LOG(INFO) << "ringbuf result callback. value: " << value
              << " mapPath: " << mapPath;
  };
  int numConsumed = result.value()->ConsumeAll(callback).value_or(-1);
  LOG(INFO) << "ring buffer size: " << numConsumed << " mapPath: " << mapPath;
}

} // namespace bpf
} // namespace uprobestats
} // namespace android


#include <iostream>
#include <string>
#define MAX 100
using namespace std;

struct Cliente {
    string nom;
    int saldo;
};

typedef struct Cliente Cliente;

int main() {
    int opc, n = 0;
    Cliente banco[MAX];
    do {
        int suma = 0;
        for ( int i = 0; i < n; i++ ) {
            cout << "(" << banco[i].nom << "," << banco[i ].saldo << ")";
            suma += banco[i].saldo;
        }
        cout << "[" << suma << "]" << endl;
        cout << "\nMenu Mi Banco" << endl;
        cout << "1. agregar cliente" << endl;
        cout << "2. consignar" << endl;
        cout << "0. salir" << endl;
        cout << "opcion: ";
        cin >> opc;
        switch (opc) {
        case 1:
            cout << "Nombre: ";
            cin >> banco[n].nom;
            cout << "Saldo Inicial: ";
            cin >> banco[n++].saldo;
            break;

        case 2:
            string nom;
            int valor;
            cout << "Nombre a consignar: ";
            cin >> nom;
            for ( int i = 0; i < n; i++ ) {
                if ( banco[i].nom == nom ) {
                    cout << "Monto a consignar: ";
                    cin >> valor;
                    banco[ i ].saldo += valor;
                    break;
                }
            }
            break;
        }
    }
    while (opc != 0);

    return 0;
}


// OpenArchive.cpp

#include "StdAfx.h"

#include "Common/Wildcard.h"

#include "Windows/FileDir.h"
#include "Windows/PropVariant.h"

#include "../../Common/FileStreams.h"
#include "../../Common/StreamUtils.h"

#include "DefaultName.h"
#include "OpenArchive.h"

using namespace NWindows;

// Static-SFX (for Linux) can be big.
const UInt64 kMaxCheckStartPosition = 1 << 22;

HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)
{
  NCOM::CPropVariant prop;
  result = false;
  RINOK(archive->GetProperty(index, propID, &prop));
  if (prop.vt == VT_BOOL)
    result = VARIANT_BOOLToBool(prop.boolVal);
  else if (prop.vt != VT_EMPTY)
    return E_FAIL;
  return S_OK;
}

HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)
{
  return GetArchiveItemBoolProp(archive, index, kpidIsDir, result);
}

HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
{
  {
    NCOM::CPropVariant prop;
    RINOK(Archive->GetProperty(index, kpidPath, &prop));
    if (prop.vt == VT_BSTR)
      result = prop.bstrVal;
    else if (prop.vt == VT_EMPTY)
      result.Empty();
    else
      return E_FAIL;
  }
  if (result.IsEmpty())
  {
    result = DefaultName;
    NCOM::CPropVariant prop;
    RINOK(Archive->GetProperty(index, kpidExtension, &prop));
    if (prop.vt == VT_BSTR)
    {
      result += L'.';
      result += prop.bstrVal;
    }
    else if (prop.vt != VT_EMPTY)
      return E_FAIL;
  }
  return S_OK;
}

HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const
{
  NCOM::CPropVariant prop;
  defined = false;
  ft.dwHighDateTime = ft.dwLowDateTime = 0;
  RINOK(Archive->GetProperty(index, kpidMTime, &prop));
  if (prop.vt == VT_FILETIME)
  {
    ft = prop.filetime;
    defined = true;
  }
  else if (prop.vt != VT_EMPTY)
    return E_FAIL;
  else if (MTimeDefined)
  {
    ft = MTime;
    defined = true;
  }
  return S_OK;
}

#ifndef _SFX
static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size)
{
  for (size_t i = 0; i < size; i++)
    if (p1[i] != p2[i])
      return false;
  return true;
}
#endif

#ifdef UNDER_CE
static const int kNumHashBytes = 1;
#define HASH_VAL(buf, pos) ((buf)[pos])
#else
static const int kNumHashBytes = 2;
#define HASH_VAL(buf, pos) ((buf)[pos] | ((UInt32)(buf)[pos + 1] << 8))
#endif

HRESULT CArc::OpenStream(
    CCodecs *codecs,
    int formatIndex,
    IInStream *stream,
    ISequentialInStream *seqStream,
    IArchiveOpenCallback *callback)
{
  Archive.Release();
  ErrorMessage.Empty();
  const UString fileName = ExtractFileNameFromPath(Path);
  UString extension;
  {
    int dotPos = fileName.ReverseFind(L'.');
    if (dotPos >= 0)
      extension = fileName.Mid(dotPos + 1);
  }
  CIntVector orderIndices;
  if (formatIndex >= 0)
    orderIndices.Add(formatIndex);
  else
  {

  int i;
  int numFinded = 0;
  for (i = 0; i < codecs->Formats.Size(); i++)
    if (codecs->Formats[i].FindExtension(extension) >= 0)
      orderIndices.Insert(numFinded++, i);
    else
      orderIndices.Add(i);

  if (!stream)
  {
    if (numFinded != 1)
      return E_NOTIMPL;
    orderIndices.DeleteFrom(1);
  }

  #ifndef _SFX
  if (orderIndices.Size() >= 2 && (numFinded == 0 || extension.CompareNoCase(L"exe") == 0))
  {
    CIntVector orderIndices2;
    CByteBuffer byteBuffer;
    const size_t kBufferSize = (1 << 21);
    byteBuffer.SetCapacity(kBufferSize);
    RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
    size_t processedSize = kBufferSize;
    RINOK(ReadStream(stream, byteBuffer, &processedSize));
    if (processedSize == 0)
      return S_FALSE;

    const Byte *buf = byteBuffer;
    CByteBuffer hashBuffer;
    const UInt32 kNumVals = 1 << (kNumHashBytes * 8);
    hashBuffer.SetCapacity(kNumVals);
    Byte *hash = hashBuffer;
    memset(hash, 0xFF, kNumVals);
    Byte prevs[256];
    if (orderIndices.Size() >= 256)
      return S_FALSE;
    int i;
    for (i = 0; i < orderIndices.Size(); i++)
    {
      const CArcInfoEx &ai = codecs->Formats[orderIndices[i]];
      const CByteBuffer &sig = ai.StartSignature;
      if (sig.GetCapacity() < kNumHashBytes)
        continue;
      UInt32 v = HASH_VAL(sig, 0);
      prevs[i] = hash[v];
      hash[v] = (Byte)i;
    }

    processedSize -= (kNumHashBytes - 1);
    for (UInt32 pos = 0; pos < processedSize; pos++)
    {
      for (; pos < processedSize && hash[HASH_VAL(buf, pos)] == 0xFF; pos++);
      if (pos == processedSize)
        break;
      UInt32 v = HASH_VAL(buf, pos);
      Byte *ptr = &hash[v];
      int i = *ptr;
      do
      {
        int index = orderIndices[i];
        const CArcInfoEx &ai = codecs->Formats[index];
        const CByteBuffer &sig = ai.StartSignature;
        if (sig.GetCapacity() != 0 && pos + sig.GetCapacity() <= processedSize + (kNumHashBytes - 1) &&
            TestSignature(buf + pos, sig, sig.GetCapacity()))
        {
          orderIndices2.Add(index);
          orderIndices[i] = 0xFF;
          *ptr = prevs[i];
        }


// dear imgui: Renderer Backend for Vulkan
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)

// Implemented features:
//  [!] Renderer: User texture binding. Use 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.
//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
//  [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.

// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/

// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// Learn about Dear ImGui:
// - FAQ                  https://dearimgui.com/faq
// - Getting Started      https://dearimgui.com/getting-started
// - Documentation        https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp

// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
//   You will use those if you want to use this rendering backend in your engine/app.
// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
//   the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
// Read comments in imgui_impl_vulkan.h.

// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
//  2025-07-27: Vulkan: Fixed texture update corruption introduced on 2025-06-11. (#8801, #8755, #8840)
//  2025-07-07: Vulkan: Fixed texture synchronization issue introduced on 2025-06-11. (#8772)
//  2025-06-27: Vulkan: Fixed validation errors during texture upload/update by aligning upload size to 'nonCoherentAtomSize'. (#8743, #8744)
//  2025-06-11: Vulkan: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplVulkan_CreateFontsTexture() and ImGui_ImplVulkan_DestroyFontsTexture().
//  2025-05-07: Vulkan: Fixed validation errors during window detach in multi-viewport mode. (#8600, #8176)
//  2025-05-07: Vulkan: Load dynamic rendering functions using vkGetDeviceProcAddr() + try both non-KHR and KHR versions. (#8600, #8326, #8365)
//  2025-04-07: Vulkan: Deep-copy ImGui_ImplVulkan_InitInfo::PipelineRenderingCreateInfo's pColorAttachmentFormats buffer when set, in order to reduce common user-error of specifying a pointer to data that gets out of scope. (#8282)
//  2025-02-14: *BREAKING CHANGE*: Added uint32_t api_version to ImGui_ImplVulkan_LoadFunctions().
//  2025-02-13: Vulkan: Added ApiVersion field in ImGui_ImplVulkan_InitInfo. Default to header version if unspecified. Dynamic rendering path loads "vkCmdBeginRendering/vkCmdEndRendering" (without -KHR suffix) on API 1.3. (#8326)
//  2025-01-09: Vulkan: Added IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE to clarify how many image sampler descriptors are expected to be available in descriptor pool. (#6642)
//  2025-01-06: Vulkan: Added more ImGui_ImplVulkanH_XXXX helper functions to simplify our examples.
//  2024-12-11: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222)
//  2024-11-27: Vulkan: Make user-provided descriptor pool optional. As a convenience, when setting init_info->DescriptorPoolSize the backend will create one itself. (#8172, #4867)
//  2024-10-07: Vulkan: Changed default texture sampler to Clamp instead of Repeat/Wrap.
//  2024-10-07: Vulkan: Expose selected render state in ImGui_ImplVulkan_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
//  2024-10-07: Vulkan: Compiling with '#define ImTextureID=ImU64' is unnecessary now that dear imgui defaults ImTextureID to u64 instead of void*.
//  2024-04-19: Vulkan: Added convenience support for Volk via IMGUI_IMPL_VULKAN_USE_VOLK define (you can also use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)
//  2024-02-14: *BREAKING CHANGE*: Moved RenderPass parameter from ImGui_ImplVulkan_Init() function to ImGui_ImplVulkan_InitInfo structure. Not required when using dynamic r


// dear imgui: Platform Binding for Android native app
// This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3)

// Implemented features:
//  [X] Platform: Keyboard arrays indexed using AKEYCODE_* codes, e.g. ImGui::IsKeyPressed(AKEYCODE_SPACE).
// Missing features:
//  [ ] Platform: Clipboard support.
//  [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
//  [ ] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
// Important:
//  - FIXME: On-screen keyboard currently needs to be enabled by the application (see examples/ and issue #3446)
//  - FIXME: Unicode character inputs needs to be passed by Dear ImGui by the application (see examples/ and issue #3446)

// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs

// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
//  2021-03-04: Initial version.

#include "imgui.h"
#include "imgui_impl_android.h"
#include <time.h>
#include <map>
#include <queue>
#include <android/native_window.h>
#include <android/input.h>
#include <android/keycodes.h>
#include <android/log.h>

// Android data
static double                                   g_Time = 0.0;
static ANativeWindow*                           g_Window;
static char                                     g_LogTag[] = "ImGuiExample";
static std::map<int32_t, std::queue<int32_t>>   g_KeyEventQueues; // FIXME: Remove dependency on map and queue once we use upcoming input queue.

int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event)
{
    ImGuiIO& io = ImGui::GetIO();
    int32_t event_type = AInputEvent_getType(input_event);
    switch (event_type)
    {
    case AINPUT_EVENT_TYPE_KEY:
    {
        int32_t event_key_code = AKeyEvent_getKeyCode(input_event);
        int32_t event_action = AKeyEvent_getAction(input_event);
        int32_t event_meta_state = AKeyEvent_getMetaState(input_event);

        io.KeyCtrl = ((event_meta_state & AMETA_CTRL_ON) != 0);
        io.KeyShift = ((event_meta_state & AMETA_SHIFT_ON) != 0);
        io.KeyAlt = ((event_meta_state & AMETA_ALT_ON) != 0);

        switch (event_action)
        {
        // FIXME: AKEY_EVENT_ACTION_DOWN and AKEY_EVENT_ACTION_UP occur at once as soon as a touch pointer
        // goes up from a key. We use a simple key event queue/ and process one event per key per frame in
        // ImGui_ImplAndroid_NewFrame()...or consider using IO queue, if suitable: https://github.com/ocornut/imgui/issues/2787
        case AKEY_EVENT_ACTION_DOWN:
        case AKEY_EVENT_ACTION_UP:
            g_KeyEventQueues[event_key_code].push(event_action);
            break;
        default:
            break;
        }
        break;
    }
    case AINPUT_EVENT_TYPE_MOTION:
    {
        int32_t event_action = AMotionEvent_getAction(input_event);
        int32_t event_pointer_index = (event_action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
        event_action &= AMOTION_EVENT_ACTION_MASK;
        switch (event_action)
        {
        case AMOTION_EVENT_ACTION_DOWN:
        case AMOTION_EVENT_ACTION_UP:
            // Physical mouse buttons (and probably other physical devices) also invoke the actions AMOTION_EVENT_ACTION_DOWN/_UP,
            // but we have to process them separately to identify the actual button pressed. This is done below via
            // AMOTION_EVENT_ACTION_BUTTON_PRESS/_RELEASE. Here, we only process "FINGER" input (and "UNKNOWN", as a fallback).
            if((AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_FINGER)
            || (AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_UNKNOWN))
            {
                io.MouseDown[0] = (event_action == AMOTION_EVENT_ACTION_DOWN);
                io.MousePos = ImVec2(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
            }
            break;
        case AMOTION_EVENT_ACTION_BUTTON_PRESS:
        case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
            {
                int32_t button_state = AMotionEvent_getButtonState(input_event);
                io.MouseDown[0] = ((button_state & AMOTION_EVENT_BUTTON_PRIMARY) != 0);
                io.MouseDown[1] = ((button_state & AMOTION_EVENT_BUTTON_SECONDARY) != 0);
                io.MouseDown[2] = ((button_state & AMOTION_EVENT_BUTTON_TERTIARY) != 0);
            }
            break;


#include <QTRSensors.h>
QTRSensors qtr;
const uint8_t sensorCount = 11;
uint16_t sensorValues[sensorCount];
int sensorThreshold[11] = {400,400,400,400,400,400,400,400,400,400,400};

#define rightMotorPin A0
#define leftMotorPin A1

class sensorsObject {
  int sensorCount_;
  int* sensorPins_;
  int* sensorThresholds_;
  int* sensorValues_;

 sensorsObject(int sensorCount, int* sensorPins, int* sensorThreshold){
 this->sensorCount_ = sensorCount;
 for(int _i=0; _i < sensorCount; _i++){
  this->sensorPins_[_i]=sensorPins[_i];
  this->sensorThresholds_[_i]=sensorThreshold[_i];
  this->sensorValues_[_i]=0;
 }
 }
};
void readArray(){
    qtr.read(sensorValues);
  for (uint8_t i = 0; i < sensorCount; i++)
  {
    Serial.print(sensorValues[i]);
    Serial.print('\t');
  }
  Serial.print('\t');

  for (uint8_t i = 0; i < sensorCount; i++)
  {
    if (sensorValues[i] > sensorThreshold[i])
    {
      Serial.print("X");  // black surface detected
    }
    else
    {
      Serial.print("-");  // white surface detected
    }
  }
  Serial.println();
  delay(50);
}
};

void setup()
{
  //Motor motorRL(rightMotorSpeed 0, leftMotorSpeed 0);

  Serial.begin(9600);
  qtr.setTypeRC();
  qtr.setSensorPins((const uint8_t[]){12,11,10, 9, 8, 7, 6, 5,4,3,2}, sensorCount);
  // correlating sensor               22,20,18,16,14,13,12,10,8,6,4
}

void loop()
{
sensorsObject sensors1(sensorCount, sensorPins, sensorThreshold)

}


#include "game_object.hpp"

#include <queue>
#include <iostream>
#include "collision_calculator.hpp"

#define abs(x) ((x) > 0 ? (x) : -(x))
#define sign(x) ((x) > 0 ? 1 : ((x) < 0 ? -1 : 0))
#define norm(vec) (std::sqrt(vec.x * vec.x + vec.y * vec.y))
#define normalized(vec) (vec.x == 0 && vec.y == 0 ? sf::Vector2f(0, 0) : (1 / norm(vec)) * vec)

void GameObject::calculateCollision(std::shared_ptr<GameObject> first, std::shared_ptr<GameObject> second, bool notify)
{
    if (first.get() == second.get())
        return;
    if (!first->collidable || !second->collidable)
        return;
    if (!first->physical && !second->physical)
        return;
    if (first->collidable->trigger && second->collidable->trigger)
        return;
    const Hitbox &firstHitbox = first->collidable->getHitbox();
    const Hitbox &secondHitbox = second->collidable->getHitbox();
    sf::Vector2f penetration;

    switch (secondHitbox.index())
    {
    case 0: // circle

    case 1: // convex
    {
        auto simplex = collision_calculator::getGJKCollisionSimplex(firstHitbox, secondHitbox);
        if (simplex.size() == 0)
            return;
        if (notify)
        {
            first->collidable->colliding.emplace_back(second);
            second->collidable->colliding.emplace_back(first);
            first->onCollision(second);
            second->onCollision(first);
            notify = false;
            if (first->collidable->trigger || second->collidable->trigger)
                return;
        }
        penetration = -collision_calculator::getPenetrationVector(firstHitbox, secondHitbox, simplex);
        break;
    }

    case 2: // concave
    {
        auto &triangles = std::get<ConcaveHitbox>(secondHitbox).triangles;
        size_t count = 0;
        for (auto triangle : triangles)
        {
            auto simplex = collision_calculator::getGJKCollisionSimplex(firstHitbox, triangle);
            if (simplex.size() == 0)
                continue;
            if (notify)
            {
                first->collidable->colliding.emplace_back(second);
                second->collidable->colliding.emplace_back(first);
                first->onCollision(second);
                second->onCollision(first);
                notify = false;
                if (first->collidable->trigger || second->collidable->trigger)
                    return;
            }
            penetration -= collision_calculator::getPenetrationVector(firstHitbox, triangle, simplex);
            count++;
        }
        if (count == 0)
            return;
        penetration = {penetration.x / count, penetration.y / count};
        break;
    }

    default:
        return;
    }
    // на всякий случай
    if (norm(penetration) > 40)
        return;
    float firstMass = first->physical ? first->physical->mass : -1;
    float secondMass = second->physical ? second->physical->mass : -1;
    if (firstMass != -1 && secondMass != -1)
    {
        float coef = firstMass / (firstMass + secondMass);
        first->move((1 - coef) * penetration);
        first->physical->speed += (1 - coef) * penetration;
        second->move(-coef * penetration);
        second->physical->speed -= coef * penetration;
        // if (first->collidable->prevColliding.find(second->tag) == first->collidable->prevColliding.end())
        // {
        //     sf::Vector2f newVel = coef * first->physical->speed + (1 - coef) * second->physical->speed;
        //     first->physical->speed = newVel;
        //     second->physical->speed = newVel;
        // }
    }
    else if (firstMass != -1)
    {
        first->move(penetration);
        first->physical->speed += penetration;
        // friction
        sf::Vector2f perpPen = sf::Vector2f(-penetration.y, penetration.x);
        float vt = first->physical->speed.x * perpPen.x + first->physical->speed.y * perpPen.y;
        sf::Vector2f fricDir = -1.f * sign(vt) * normalized(perpPen);
        first->physical->speed += fricDir * first->physical->mass * 0.02f * second->collidable->fricCoef;
    }
    else
    {
        second->move(-penetration);
        second->physical->speed -= penetration;
        // friction
        sf::Vector2f perpPen = sf::Vector2f(-penetration.y, penetration.x);
        float vt = second->physical->speed.x * perpPen.x + second->physical->speed.y * perpPen.y;
        sf::Vector2f fricDir = -1.f * sign(vt) * normalized(perpPen);
        second->physical->speed += fricDir * second->physical->mass * 0.02f * first->collidable->fricCoef;
    }
}

void GameObject::update(std::shared_ptr<GameObject> obj)
{
    std::queue<std::shared_ptr<GameObject>> objects;
    objects.push(obj);
    while (objects.size() != 0)
    {
        std::shared_ptr<GameObject> cur = objects.front();
        cur->update();
        if (cur->physical)
        {
            cur->physical->update();
            cur->move(cur->physical->speed);
        }
        if (cur->collidable)
        {
            cur->collidable->prevColliding


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

#include "napi/native_api.h"
#include "hilog/log.h"
#include <fstream>
#include <iostream>
#include <cstring>
#include <ctime>
#include <js_native_api.h>
#include <js_native_api_types.h>
#include <client/ovpncli.hpp>
#include <openvpn/tun/builder/capture.hpp>
#include "model.hpp"
#include <json/json.h>

#define MAKE_FILE_NAME (strrchr(__FILE__, '/') + 1)

#define NETMANAGER_VPN_LOGE(fmt, ...)                                                                                \
    OH_LOG_Print(LOG_APP, LOG_ERROR, 0x15b0, "NetMgrVpn", "vpn [%{public}s %{public}d] " fmt, MAKE_FILE_NAME,          \
                 __LINE__, ##__VA_ARGS__)

#define NETMANAGER_VPN_LOGI(fmt, ...)                                                                                \
    OH_LOG_Print(LOG_APP, LOG_INFO, 0x15b0, "NetMgrVpn", "vpn [%{public}s %{public}d] " fmt, MAKE_FILE_NAME, __LINE__, \
                 ##__VA_ARGS__)

#define NETMANAGER_VPN_LOGD(fmt, ...)                                                                                \
    OH_LOG_Print(LOG_APP, LOG_DEBUG, 0x15b0, "NetMgrVpn", "vpn [%{public}s %{public}d] " fmt, MAKE_FILE_NAME,          \
                 __LINE__, ##__VA_ARGS__)

napi_ref cb_protect_ref = nullptr;
napi_ref cb_tun_ref = nullptr;
napi_ref cb_connected_ref = nullptr;
napi_threadsafe_function tsfn_protect, tsfn_tun, tsfn_connected; // 线程安全函数

int tun_fd = -1;
bool tun_done = false;
std::mutex tun_mtx;
std::condition_variable tun_cv;
std::string files_dir;

napi_value ArkTsTunCallBack(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value v;
    napi_get_cb_info(env, info, &argc, &v, nullptr, nullptr);

    NETMANAGER_VPN_LOGI("TunThenLock, %{public}d", tun_fd);
    std::unique_lock<std::mutex> lock(tun_mtx);
    napi_get_value_int32(env, v, &tun_fd);
    tun_done = true;
    tun_cv.notify_all(); // 通知主线程继续执行
    NETMANAGER_VPN_LOGI("TunThenFinished, %{public}d", tun_fd);
    return nullptr;
}

void call_js_tun(napi_env env, napi_value js_cb, void *context, void *data) {
    napi_get_reference_value(env, cb_tun_ref, &js_cb);
    auto v = static_cast<std::string *>(data);

    napi_value cfg, promise;
    napi_create_string_utf8(env, v->c_str(), v->length(), &cfg);
    napi_call_function(env, nullptr, js_cb, 1, &cfg, &promise);

    // 获取promise对象的then属性，该属性的回调方法用于处理ArkTS侧异步计算结果
    napi_value thenProperty = nullptr;
    napi_get_named_property(env, promise, "then", &thenProperty);
    // 将C++语言定义的then属性回调方法转换为ArkTS函数对象，即napi_value类型值
    napi_value thenCallback = nullptr;
    napi_create_function(env, "thenCallback", NAPI_AUTO_LENGTH, ArkTsTunCallBack, nullptr, &thenCallback);

    // 获取promise对象的catch属性，该属性的回调方法用于处理ArkTS侧异步计算异常的信息
    napi_value catchProperty = nullptr;
    napi_get_named_property(env, promise, "catch", &catchProperty);
    // 将C++语言定义的catch属性回调方法转换为ArkTS函数对象，即napi_value类型值
    napi_value catchCallback = nullptr;
    napi_create_function(
        env, "catchCallback", NAPI_AUTO_LENGTH,
        [](napi_env env, napi_callback_info info) -> napi_value {
            size_t argc = 1;
            napi_value args[1] = {nullptr};
            napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
            size_t strLen = 0;
            napi_get_value_string_utf8(env, args[0], nullptr, 0, &strLen); // 获取字符串长度到strLen
            char *strBuffer = new char[strLen + 1];                        // 分配合适大小的char数组
            napi_get_value_string_utf8(env, args[0], strBuffer, strLen + 1, &strLen);
            NETMANAGER_VPN_LOGE("ArkTS Async Method Calculation Exception: %{public}s", strBuffer);
            return nullptr;
        },
        nullptr, &catchCallback);

    // 通过napi_call_function执行then属性的回调，类似于ArkTS侧调用promise.then(()=>{})
    napi_call_function(env, promise, thenProperty, 1, &thenCallback, nullptr);
    // 通过napi_call_function执行catch属性的回调，类似于ArkTS侧调用promise.catch(()=>{})
    napi_call_function(env, promise, catchProperty, 1, &catchCallback, nullptr);
//     napi_delete_reference(env, cb_protect_ref);
}

static int g_vpnNetId;

class Client : public openvpn::ClientAPI::OpenVPNClient {
private:
    VpnConfig tun;
    NetAddress tun_gw; // gateway
    std::vector<std::string> tun_proxy_bypasses;
//     NetConn_HttpProxy tun_proxy_http;
    std::string tun_proxy_host;
    int tun_proxy_port;
    std::ofstream logFd;

public:
    ~Client() {
        if


#include <iostream>
bool PVP_logic_horizontal_player_1(char backend_grid[][5],bool is_running1){
    int sum =0;
    for (int i=0;i<1;i+=2){
        for(int j=0;j<5;j+=2){
            sum += backend_grid[i][j] - '0';
        }
    }
    if (sum ==27 ){
        std::cout <<"----------------------------------------------------------\n";
        std::cout <<"-------------------PLAYER 1 WINS--------------------------\n";
        std::cout <<"----------------------------------------------------------\n";
        return false;
    }
    sum = 0;
    for (int k=2;k<3;k+=2){
        for(int l=0;l<5;l+=2){
            sum += backend_grid[k][l] - '0';
        }
    }
    if (sum ==27 ){
        std::cout <<"----------------------------------------------------------\n";
        std::cout <<"-------------------PLAYER 1 WINS--------------------------\n";
        std::cout <<"----------------------------------------------------------\n";
        return false;
    }
    sum = 0;
    for (int m=4;m<5;m+=2){
        for(int n=0;n<5;n+=2){
            sum += backend_grid[m][n] - '0';
        }
    }
    if (sum ==27 ){
        std::cout <<"----------------------------------------------------------\n";
        std::cout <<"-------------------PLAYER 1 WINS--------------------------\n";
        std::cout <<"----------------------------------------------------------\n";
        return false;
    }
    return true;
}
bool PVP_logic_vertical_player_1(char backend_grid[][5],bool is_running2){
    int sum =0;
    for (int i=0;i<5;i+=2){
        for(int j=0;j<1;j+=2){
            sum += backend_grid[i][j] - '0';

        }
    }
    if (sum ==27 ){
        std::cout <<"----------------------------------------------------------\n";
        std::cout <<"-------------------PLAYER 1 WINS--------------------------\n";
        std::cout <<"----------------------------------------------------------\n";
        return false;
    }
    sum = 0;
    for (int k=0;k<5;k+=2){
        for(int l=2;l<3;l+=2){
            sum += backend_grid[k][l] - '0';
        }
    }
    if (sum ==27 ){
        std::cout <<"----------------------------------------------------------\n";
        std::cout <<"-------------------PLAYER 1 WINS--------------------------\n";
        std::cout <<"----------------------------------------------------------\n";
        return false;
    }
    sum = 0;
    for (int m=0;m<5;m+=2){
        for(int n=4;n<5;n+=2){
            sum += backend_grid[m][n] - '0';
        }
    }
    if (sum ==27 ){
        std::cout <<"----------------------------------------------------------\n";
        std::cout <<"-------------------PLAYER 1 WINS--------------------------\n";
        std::cout <<"----------------------------------------------------------\n";
        return false;
    }
    return true;
}
bool PVP_logic_diagonal_1_player_1(char backend_grid[][5],bool is_running3){
    int sum =0;
    int m =0;
    for (int i=0;i<5;i+=2){
        for(int j=m;j<m+1;j+=5){
            sum += backend_grid[i][j] - '0';
        }
        m+=2;
    }
    if (sum ==27 ){
        std::cout <<"----------------------------------------------------------\n";
        std::cout <<"-------------------PLAYER 1 WINS--------------------------\n";
        std::cout <<"----------------------------------------------------------\n";
        return false;
    }
    return true;
}
bool PVP_logic_diagonal_2_player_1(char backend_grid[][5],bool is_running4){
    int sum = 0;
    int n =4;
    for (int k=0;k<5;k+=2){
        for(int l=n;l>=n;l-=5){
            sum += backend_grid[k][l] - '0';
        }
        n-=2;
    }
    if (sum ==27 ){
        std::cout <<"----------------------------------------------------------\n";
        std::cout <<"-------------------PLAYER 1 WINS--------------------------\n";
        std::cout <<"----------------------------------------------------------\n";
        return false;
    }
    return true;
}
bool PVP_logic_horizontal_player_2(char backend_grid[][5],bool is_running5){
    int sum =0;
    for (int i=0;i<1;i+=2){
        for(int j=0;j<5;j+=2){
            sum += backend_grid[i][j] - '0';
        }
    }
    if (sum ==9 ){
        std::cout <<"----------------------------------------------------------\n";
        std::cout <<"-------------------PLAYER 2 WINS--------------------------\n";
        std::cout <<"----------------------------------------------------------\n";
        return false;
    }
    sum = 0;
    for (int k=2;k<3;k+=2){
        for(int l=0;l<5;l+=2){
            sum += backend_grid[k][l] - '0';
        }
    }
    if (sum ==9 ){
        std::cout <<"----------------------------------------------------------\n";
        std::cout <<"-------------------PLAYER 2 WINS--------------------------\n";
        std::cout <<"----------------------------------------------------------\n";
        return false;
    }
    sum = 0;
    for (int m=4;m<5;m+=2){
        for(int n=0;n<5;n+=2){
            sum += backend_grid[m][n]


#include "pvs_mt.h"

#include <algorithm>
#include <functional>
#include <condition_variable>
#include <chrono>
#include "search_control.h"
#include "evaluation/evaluation.h"

constexpr inline int pieceValue(Figures figure) {
    return figure;
}

// Удобные константы
static constexpr int INF = 1000000000;
static constexpr int MATE = 100000;

// Forward: внутренняя quiescence (negamax-конвенция — score с точки зрения стороны на ходу)
static int quiescence_local(Position& pos, int alpha, int beta);

// ---------------------- Sequential PVS (negamax-style) ----------------------
SearchResult pvs_seq(Position& pos, int depth, int alpha, int beta, TranspositionTable& tt) {
    SearchResult res{};
    res.bestMove = Move{-1,-1,-1,-1, EMPTY};
    res.depth = depth;

    if (search_control::shouldStop()) {
        res.score = 0;
        return res;
    }

    uint64_t key = computeHash(pos);
    int alphaOrig = alpha;

    // TT probe
    int ttScore = 0;
    Move ttMove{-1,-1,-1,-1, EMPTY};
    if (tt.probe(key, depth, alpha, beta, ttScore, ttMove)) {
        res.score = ttScore;
        res.bestMove = ttMove;
        return res;
    }

    if (depth <= 0) {
        res.score = quiescence_local(pos, alpha, beta);
        return res;
    }

    std::vector<Move> moves = pos.getLegalMoves();
    if (moves.empty()) {
        if (pos.isCheck()) res.score = -MATE + depth;
        else res.score = 0;
        return res;
    }

    // ordering: ttMove first
    if (ttMove.fromX != -1) {
        auto it = std::find_if(moves.begin(), moves.end(), [&](const Move& m){
            return m.fromX==ttMove.fromX && m.fromY==ttMove.fromY &&
                   m.toX==ttMove.toX && m.toY==ttMove.toY && m.promotion==ttMove.promotion;
        });
        if (it != moves.end()) std::iter_swap(moves.begin(), it);
    }

    // simple MVV/LVA-like sort for remaining
    std::stable_sort(moves.begin()+1, moves.end(), [&](const Move& a, const Move& b){
        Piece ta = pos.getPiece(a.toX, a.toY);
        Piece tb = pos.getPiece(b.toX, b.toY);
        int va = (ta.getType()==EMPTY && !a.isEnPassant) ? 0 : pieceValue(ta.getType());
        int vb = (tb.getType()==EMPTY && !b.isEnPassant) ? 0 : pieceValue(tb.getType());
        return va > vb;
    });

    int bestScore = -INF;
    Move bestMove = Move{-1,-1,-1,-1, EMPTY};
    bool first = true;

    for (const Move& m : moves) {
        if (search_control::shouldStop()) break;

        Position child = pos;
        child.applyMove(m);

        int val;
        if (first) {
            SearchResult sr = pvs_seq(child, depth-1, -beta, -alpha, tt);
            val = -sr.score;
            first = false;
        } else {
            SearchResult sr = pvs_seq(child, depth-1, -alpha-1, -alpha, tt);
            val = -sr.score;
            if (val > alpha && val < beta) {
                SearchResult sr2 = pvs_seq(child, depth-1, -beta, -alpha, tt);
                val = -sr2.score;
            }
        }

        if (val > bestScore) {
            bestScore = val;
            bestMove = m;
        }
        if (bestScore > alpha) alpha = bestScore;
        if (alpha >= beta) break;
    }

    res.score = bestScore;
    res.bestMove = bestMove;

    // store in TT
    BoundType bound = BoundType::EXACT;
    if (bestScore <= alphaOrig) bound = BoundType::UPPER;
    else if (bestScore >= beta) bound = BoundType::LOWER;
    tt.store(key, depth, res.score, bound, res.bestMove);
    return res;
}

// ---------------------- Local quiescence ----------------------
static int quiescence_local(Position& pos, int alpha, int beta) {
    if (search_control::shouldStop()) return 0;
    int stand = evaluate(pos); // предполагаем, что evaluate уже в negamax-конвенции (side to move)
    // Если evaluate возвращает с точки зрения белых, распакуйте/инвертируйте заранее.
    if (stand >= beta) return beta;
    if (stand > alpha) alpha = stand;

    std::vector<Move> moves = pos.getLegalMoves();
    bool inCheck = pos.isCheck();

    // sort captures first
    std::stable_sort(moves.begin(), moves.end(), [&](const Move& a, const Move& b){
        Piece ta = pos.getPiece(a.toX, a.toY);
        Piece tb = pos.getPiece(b.toX, b.toY);
        int va = (ta.getType()==EMPTY && !a.isEnPassant) ? 0 : pieceValue(ta.getType());
        int vb = (tb.getType()==EMPTY && !b.isEnPassant) ? 0 : pieceValue(tb.getType());
        return va > vb;
    });

    for (const Move& m : moves) {
        if (search_control::shouldStop()) break;

        Piece tgt = pos.getPiece(m.toX, m.toY);
        bool isCap = (tgt.getType() != EMPTY) || m.isEnPassant;
        if (!inCheck && !isCap) continue;

        Position child = pos;
        child.applyMove(m);
        int score = -quiescence_local(child, -beta, -alpha);
        if (score >= beta) return beta;
        if (score > alpha) alpha = score;
    }
    return alpha;
}

// ---------------------- Multi-threaded node search (YBWC-style simplified) ----------------------
SearchResult pvs_mt


#include "global.h"
#include "utils/messages.hpp"
#include "utils/utils.hpp"
#include <core.h>
#include <filesystem>
#include <hilog/log.h>
#include <js_native_api_types.h>
#include <memory>
#include <nlohmann/json.hpp>
#include <node_api_types.h>
#include <rawfile/raw_file_manager.h>
#include <repo_manager.h>

Core Core::instance_{};

napi_value Core::InitSystem(napi_env env, napi_callback_info info) noexcept {
    char const *from = "Core::InitSystem-NAPI";
    OH_LOG_INFO(LOG_APP, "================= Core::InitSystem-NAPI =================");

    constexpr size_t expectedParams = 1U;
    constexpr size_t basePathIdx = 0U;

    size_t argc = expectedParams;
    napi_value argv[expectedParams]{};

    bool const result = Utils::extractParameters(env, info, expectedParams, &argc, argv, from);
    if (!result) {
        return nullptr;
    }

    auto const basePath = Utils::extractString(env, argv[basePathIdx], "Can't extract basePath", from);
    if (!basePath.has_value()) {
        return nullptr;
    }

    Globals::files_directory = basePath.value();

    OH_LOG_INFO(LOG_APP, "basePath: %{public}s", basePath.value().c_str());

    // init ssh
    Core::GetInstance()->InitSSH(basePath.value());

    return Messages::NewResultMessage(env, true, "初始化系统成功");
}

napi_value Core::InitRepo(napi_env env, napi_callback_info info) noexcept {
    char const *from = "Core::InitRepo-NAPI";
    OH_LOG_INFO(LOG_APP, "================= Core::InitRepo-NAPI =================");
    constexpr size_t expectedParams = 4U;
    constexpr size_t basePathIdx = 0U;
    constexpr size_t repoURLIdx = 1U;
    constexpr size_t repoNameIdx = 2U;
    constexpr size_t providerIdx = 3U;

    size_t argc = expectedParams;
    napi_value argv[expectedParams]{};

    bool const result = Utils::extractParameters(env, info, expectedParams, &argc, argv, from);
    if (!result) {
        return nullptr;
    }

    auto const basePath = Utils::extractString(env, argv[basePathIdx], "Can't extract basePath", from);
    if (!basePath.has_value()) {
        return nullptr;
    }

    auto const repoURL = Utils::extractString(env, argv[repoURLIdx], "Can't extract repoURL", from);
    if (!repoURL.has_value()) {
        return nullptr;
    }

    auto const repoName = Utils::extractString(env, argv[repoNameIdx], "Can't extract repoName", from);
    if (!repoName.has_value()) {
        return nullptr;
    }

    auto const provider = Utils::extractString(env, argv[providerIdx], "Can't extract provider", from);
    if (!provider.has_value()) {
        return nullptr;
    }

    OH_LOG_INFO(LOG_APP, "basePath: %{public}s, repoName: %{public}s", basePath.value().c_str(),
                repoName.value().c_str());
    OH_LOG_INFO(LOG_APP, "repoURL: %{public}s", repoURL.value().c_str());

    auto repoDir = basePath.value() + "/repos/" + provider.value() + "/" + repoName.value();

    if (Core::GetInstance()->FindRepoManager(repoURL.value()) != nullptr) {
        OH_LOG_INFO(LOG_APP, "RepoManager already exists for url: %{public}s", repoURL.value().c_str());
        return Messages::NewResultMessage(env, true, "初始化仓库成功");
    }

    // 新建 RepoManager 并按目录是否存在决定 open 或 init
    auto manager = std::make_unique<RepoManager>();

    bool ok = false;
    if (std::filesystem::exists(repoDir)) {
        // 目录存在，视为已创建过仓库：打开
        OH_LOG_INFO(LOG_APP, "Open existing repo at: %{public}s", repoDir.c_str());
        ok = manager->openRepository(repoDir);
        ok = manager->connectRemote(repoURL.value(), repoDir);
    } else {
        // 目录不存在，创建目录并初始化裸仓库
        if (std::filesystem::create_directories(repoDir)) {
            OH_LOG_INFO(LOG_APP, "Create directory success: %{public}s", repoDir.c_str());
        } else {
            OH_LOG_ERROR(LOG_APP, "Create directory failed: %{public}s", repoDir.c_str());
            return Messages::NewResultMessage(env, false, "创建目录失败");
        }
        OH_LOG_INFO(LOG_APP, "Init new bare repo at: %{public}s", repoDir.c_str());
        ok = manager->connectRemote(repoURL.value(), repoDir);
    }

    if (!ok) {
        OH_LOG_ERROR(LOG_APP, "Init/open repository failed at: %{public}s, error: %{public}s", repoDir.c_str(),
                     manager->getLastError().c_str());
        return Messages::NewResultMessage(env, false, manager->getLastError());
    }
    OH_LOG_INFO(LOG_APP, "Init/open Repo success");
    // 放入 Core 的内存缓存，key 为 repoURL
    Core::GetInstance()->StoreRepoManager(repoURL.value(), std::move(manager));

    return Messages::NewResultMessage(env, true, "初始化仓库成功");
}

napi_value Core::GetBranches(napi_env env, napi_callback_info info) noexcept {
    char const *from = "Core::GetBranches-NAPI";
    OH_LOG_INFO(LOG_APP, "================= Core::GetBranches-NAPI =================");

    auto repoManager = Utils::FindRepoManager(env, info, from);
    if (repoManager == nullptr) {
        OH_LOG_INFO(LOG_APP, "仓库未初始化");
        return Messages::NewResultMessage(env, false, "仓库未初始化");
    }

    auto branches


/*
功能：
  用epoll监听外部连接进行的客户，然后把客户端投递到读取线程池进行读取网络数据

日期    2025-07-12
作者    罗家兄弟
QQ      79941308
E-Mail  79941308@qq.com
*/

#include "stdafx.h"
#include "ListenPool.h"
#include "identifier_generator.h"
#include "client_manager.h"
#include "ClientSendPool.h"

extern CClientReadPool*          clientReadPool;
extern CClientSendPool*          clientSendPool;

CListenPool::CListenPool(int nThreadCount)
{
	nProcThreadOrder = 0;
	nThreadProcessCount = 0;
 	nTrueNetThreadPoolCount = nThreadCount;
	if (nThreadCount > MaxListenThreadCount)
		nTrueNetThreadPoolCount = MaxListenThreadCount;

	if (nThreadCount <= 0)
		nTrueNetThreadPoolCount = 64 ;

	nGetCurrentThreadOrder = 0;
	unsigned long dwThread;
	bRunFlag = true;
	for (int i = 0; i < nTrueNetThreadPoolCount; i++)
	{
#ifdef OS_System_Windows
		hProcessHandle[i] = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)OnProcessThread, (LPVOID)this, 0, &dwThread);
#else
		pthread_create(&hProcessHandle[i], NULL, OnProcessThread, (void*)this);
#endif
	}
}

int   CListenPool::GetThreadOrder()
{
	std::lock_guard<std::mutex> lock(threadLock);
	int nGet = nGetCurrentThreadOrder;
	nGetCurrentThreadOrder  ++;
	return nGet;
}

CListenPool::~CListenPool()
{

}

void CListenPool::ProcessFunc()
{
	int nCurrentThreadID = GetThreadOrder();
 	bExitProcessThreadFlag[nCurrentThreadID].store(false);
	uint64_t nClientID = 0 ;
	int      ret_num;
	int      i;
	int      ret_recv;
	struct   sockaddr_in client_addr;
	socklen_t addrLength = sizeof(client_addr);
	SOCKET   cfd;
	int      ret;
	int      size = 1024 * 1024 * 1;
	u_long   iMode = 1;
	struct timeval timeOut = { 3,0 };
	socklen_t      timeOutLength = sizeof(timeOut);

	//创建epoll句柄epfd
	epfd[nCurrentThreadID] = epoll_create(1);
	//printf(" CListenPool::ProcessFunc() nCurrentThreadID = %d \r\n", nCurrentThreadID);

	while (bRunFlag.load())
	{
		ret_num = epoll_wait(epfd[nCurrentThreadID], events[nCurrentThreadID], MaxEventCount,1000);
		if (ret_num > 0)
		{
			for (i = 0; i < ret_num; i++)
			{//根据回调回来的 u64 进行查找
				ListenStructPtr ptr = GetPtrBySvrHandle(events[nCurrentThreadID][i].data.u64);
				if (ptr == NULL)
				{
 					continue;
				}

				//把socket通过accept接入
 				cfd = accept(ptr->svrSocket, (sockaddr*)&client_addr, &addrLength);
				if (cfd == -1)
				{
 					continue;
				}

				//设置发送、接收缓冲区
				ret = setsockopt(cfd, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof(size));
				ret = setsockopt(cfd, SOL_SOCKET, SO_SNDBUF, (char *)&size, sizeof(size));
#ifdef OS_System_Windows
				ret = ioctlsocket(cfd, FIONBIO, &iMode);
#else
	            ret = ::fcntl(cfd, F_SETFL, O_NONBLOCK) ;
#endif
				//设置发送、接收超时
				ret = setsockopt(cfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeOut, timeOutLength);
				ret = setsockopt(cfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeOut, timeOutLength);

				//设置不允许延时关闭
				struct linger sLinger;
				sLinger.l_onoff = 0;
				sLinger.l_linger = 1;
				int ret = setsockopt(cfd, SOL_SOCKET, SO_LINGER, (char *)&sLinger, sizeof(linger));

				client_ptr cli = client_manager_singleton::get_mutable_instance().malloc_client(ptr->srvhandle, ptr->fnread, ptr->fnclose, (0 != ptr->autoread) ? true : false, ptr->bSSLFlag, clientType_Accept, ptr->fnaccept);
				if (cli)
				{
  					cli->m_Socket  = cfd;
					memcpy((char*)&cli->tAddr4, (char*)&client_addr, sizeof(client_addr));
					cli->SetConnect(true);

					//加入客户链表
 					client_manager_singleton::get_mutable_instance().push_client(cli);

					//加入发送线程池
					clientSendPool->InsertIntoTask(cli->get_id());

					//先通知上层连接成功
					if (ptr->fnaccept)
						ptr->fnaccept(ptr->srvhandle, cli->get_id(), (void*)&client_addr);
					//加入读取线程池
					clientReadPool->InsertIntoTask(cli->get_id());
   				}
				else
				{
#ifdef OS_System_Windows
					closesocket(cfd);
#else
	                close(cfd) ;
#endif
				}
			}
		}
		else
			Sleep(5);
  	}

	bExitProcessThreadFlag[nCurrentThreadID].store(true);
}

void* CListenPool::OnProcessThread(void* lpVoid)
{
	int nRet = 0 ;
#ifndef OS_System_Windows
	pthread_detach(pthread_self()); //让子线程和主线程分离，当子线程退出时，自动释放子线程内存
#endif

	CListenPool* pThread = (CListenPool*)lpVoid;
	pThread->ProcessFunc();

#ifndef OS_System_Windows
	pthread_exit((void*)&nRet); //退出线程
#endif
	return  0;
}

void CListenPool::destroyListenPool()
{
	bRunFlag.store(false);
	std::lock_guard<std::mutex> lock(threadLock);

	//关闭所有epoll , 并且等待退出所有线程
	for (int i = 0; i < nTrueNetThreadPoolCount; i++)
	{
		if (epfd[i] != NULL)
		{
#ifdef OS_System_Windows
			epoll_close(epfd[i]);
#else
			close(epfd[i]);
#endif
		}
		while (!bExitProcessThreadFlag[i].load())
			Sleep(100);
	}

	//关闭 accept 以防外部没有调用 UnListen() 函数
	ListenStructPtrMap::iterator it;
	int nSize = 0 ;
	struct epoll_event  event;

	for (it = m_listenStructPtrMap.begin(); it != m_listenStructPtrMap.end();)
	{
  	    //执行关闭accept接入进来所有的连接SOCKET
		client_manager_singleton::get_mutable_instance().pop_server_clients((*it).second->srvhandle);

		//关闭accept的Socket套接字
#ifdef OS_System_Windows
		closesocket(


/******************************************************************************
* Copyright (C) 2025 Advanced Micro Devices, Inc. All Rights Reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/

#include "routing/routingtopology.h"

RoutingTopology::RoutingTopology(std::string gen, std::string name)
    : gen_(gen), name_(name),
      rm_(std::make_shared<ResourceMgr>(makeResource(gen, name)))
{}

// ── createDataIO ────────────────────────────────────────────────────────
std::shared_ptr<DataIO>
RoutingTopology::_createDataIO(std::string dioName, std::optional<Point> shim, DMADIRECTION direction, int channel)
{
    if (!shim) {
        throw std::runtime_error("No free shim tile for `" + std::string(dioName) + "`");
        return nullptr;
    }
    auto dio      = rm_->createDataIO(IOType::Input,shim->r, shim->c, direction, channel, dioName);
    dataios_.emplace(dio->id(), dio);
    return dio;
}

std::shared_ptr<DataIO>
RoutingTopology::createDataIO(std::string dioName, std::optional<TypeBasedTileLoc> loc,DMADIRECTION direct)
{
    //std::optional<FoundDmaSlot> ResourceMgr::freeShimNoc(std::optional<TypeBasedTileLoc> ioPaireddstTileloc,
    //                                                 DMADIRECTION direct,
    //                                                 int requesterIoId)

    /*
    struct FoundDmaSlot {
    DMADIRECTION direct;
    Point loc;
    int channel;
    */
    auto dioId = rm_->allocdioid();
    std::optional<FoundDmaSlot> foundDmaSlot = rm_->freeShimNoc(loc, direct, dioId);// optional<TileCoord>
    auto shimpoint = std::make_optional<Point>(foundDmaSlot->loc);
    return _createDataIO(dioName, shimpoint, foundDmaSlot->direct, foundDmaSlot->channel);;
}

std::shared_ptr<DataIO>
RoutingTopology::createDataIO(std::string dioName)
{
    auto shim = rm_->freeShimNoc();         // optional<TileCoord>
    return _createDataIO(dioName,shim);
}

std::vector<Point> RoutingTopology::ReserveTiles(int nums,int dioID) {
    std::vector<Point> allocatedTiles;
    auto result = rm_->reserveTiles(dioID, 8, ReservationStrategy::COLUMN_FIRST, allocatedTiles);
    return allocatedTiles;
}
bool RoutingTopology::occupyLink(Point a, Point b, const int ioId,int& portNum, PortDirection& pda, PortDirection& pdb){
    return rm_->occupyLink(a,  b, ioId,portNum, pda, pdb);
}
// ── createPath ──────────────────────────────────────────────────────────
std::optional<std::shared_ptr<const RoutingPath>>
RoutingTopology::createPath(int dioID, std::vector<Point> dsttiles) {
    std::vector<Point> wall ={};
    if (dataios_.find(dioID) == dataios_.end()) {
        return std::nullopt;
    }
    auto dio = dataios_[dioID];
    std::shared_ptr<RoutingPath> rpath = std::make_shared<RoutingPath>(rm_, dio, wall);
    bool ok = rpath->addIOTree({dsttiles});
    paths_.push_back(rpath);
    return rpath;
    /*
    if (!dio) return nullptr;

    auto region = rm_->allocateTileRegion(cols, rows);    // optional<vector<TileCoord>>
    if (!region) return nullptr;

    auto path = std::make_shared<RoutingPath>(dio->shimTile, *region);
    if (!path->connect()) {                               // hypothetical
        rm_->releaseTileRegion(*region);
        return nullptr;
    }

    paths_.push_back(path);
    return path;          // now freely shareable
    */
}


#include"cli.hpp"
#include <iostream>
#include <stdexcept>

namespace cli {

	Options	parse(int argc, char** argv) {
		Options options;

		for (int i = 1; i < argc;i++) {
			std::string_view argument = argv[i]; //every time gets the imput and checks the below conditions

			if (argument == "-h" || argument == "--help") {
				options.showHelp = true;
			}

			else if (argument == "-v" || argument == "--version") {
				options.showVersion = true;
			}

			else if (argument == "-o" || argument == "--output") {

				if (i + 1 < argc) {
					options.outputFile = argv[++i];
				}
				else {
					throw std::runtime_error("Missing file name after " + std::string(argument));
				}
			}

			else if (argument == "--include" && i + 1 < argc) {
				options.fileExtension = argv[++i];
			}

			else if (argument == "--exclude" && i + 1 < argc) {
				options.excludePattern = argv[++i];
			}

			// new:
			else if (argument == "-r" || argument == "--recent") {
				options.recent = true;
			}

			else {
				options.inputFiles.push_back(argument);
			}
		}

		if (options.inputFiles.empty() && !options.showHelp && !options.showVersion) {
			options.showHelp = true;
		}

		return options;
	}
}


class Solution {
    public:
        int thirdMax(vector<int>& nums) {

            //USING SET-> TC = O(nlogn) SP = O(n)
            // set<int, greater<int>> st(nums.begin(), nums.end());
            // if (st.size() < 3) {
            //     return *st.begin();
            // }
            // auto it = st.begin();
            // advance(it,2);
            // return *it;

            // tc = O(n) SP = O(1)
            long first=LONG_MIN, second = LONG_MIN, third = LONG_MIN;
            for(auto &a:nums){
                if(a==first || a==second || a==third) continue;
                if(a>first){
                    third = second;
                    second = first;
                    first = a;
                }
                else if(a>second && a!=first){
                    third = second;
                    second = a;
                }
                else if(a>third && a!=first && a!=second){
                    third = a;
                }
            }
            return third==LONG_MIN? first:third;
        }
    };


#include <iostream>
#include "Mylib.h"
using namespace std;

enum TT {
	RIGHT, LEFT, UP, DOWN,  // Trang thai cua Person
};

struct Toado {				// Giu toa do cua Person, Virus, Heal, Rua tay
	int x, y;
};

class Person {
public:						//Giu thong tin cua Person
	Toado Person;
	TT tt;
};
void Khoi_tao(Person& person) {     // Ham kho tao Person voi toa do (1,1)
	person.Person.x = 1;
	person.Person.y = 1;
	gotoXY(person.Person.x, person.Person.y);
	cout << "0";
	person.tt = DOWN;
}

class Corona_Game {
private:
	Toado p[80];					// Toa do cua 80 Virus
	Toado q[20];					// Toa do cua 20 Heal
	Toado y[10];					// Toa do cua 10 Rua tay
public:

	Corona_Game() {};
	~Corona_Game() {};

	// Ham tao hieu ung nhap nhay cho Heal va Rua tay
	void Nhapnhay(Person& person, Corona_Game& A) {

		//Nhap nhay cho Rua tay
		for (int i = 0; i < 10; i++) {
			if ((person.Person.x != A.y[i].x) && (person.Person.y != A.y[i].y)) {
				gotoXY(A.y[i].x, A.y[i].y);
				cout << " ";
				Sleep(3);
				SetColor(14);
				gotoXY(A.y[i].x, A.y[i].y);
				cout << "Y";
				SetColor(15);

			}
		}

		//Nhap nhay cho Heal
		for (int i = 0; i < 20; i++) {
			if ((person.Person.x != A.q[i].x) && (person.Person.y != A.q[i].y)) {
				gotoXY(A.q[i].x, A.q[i].y);
				cout << " ";
				Sleep(3);
				SetColor(2);
				gotoXY(A.q[i].x, A.q[i].y);
				cout << "+";
				SetColor(15);
			}
		}
	}

	// Ham tao Virus, Heal, Rua tay
	void Creat_Virus_Heal(Corona_Game& A) {

		//Ham tao Rua tay

		for (int i = 0; i < 10; i++) {
			SetColor(14);
			if (i == 0) { //Tao 1 Rua tay truoc
				A.y[i].x = 1 + rand() % 99;
				A.y[i].y = 1 + rand() % 24;
				gotoXY(A.y[i].x, A.y[i].y);
				cout << "Y";
				continue;
			}
			int x = i;
			int y = i;
			A.y[x].x = 1 + rand() % 99;
			A.y[x].y = 1 + rand() % 24;
			for (int j = 0; j < y; j++) {
				if (A.y[x].x == A.y[j].x && A.y[x].y == A.y[j].y) {
					A.y[x].x = 1 + rand() % 99;
					A.y[x].y = 1 + rand() % 24;
					i = 0;
				}
			}
			gotoXY(A.y[x].x, A.y[x].y);
			cout << "Y";
		}

		//Ham tao Heal
		for (int i = 0; i < 20; i++) {
			if (i == 0) { // Tao 1 Heal truoc
				SetColor(2);
				A.q[i].x = 1 + rand() % 99;
				A.q[i].y = 1 + rand() % 24;
				for (int j = 0; j < 10; j++) {
					while ((A.q[i].x == A.y[j].x) && (A.q[i].y == A.y[j].y)) {
						A.q[i].x = 1 + rand() % 99;
						A.q[i].y = 1 + rand() % 24;
						j = 0;
					}
				}
				gotoXY(A.q[i].x, A.q[i].y);
				cout << "+";
				continue;
			}
			SetColor(2);
			A.q[i].x = 1 + rand() % 99;
			A.q[i].y = 1 + rand() % 24;
			int x = i;
			int y = i;
			QuangDong: for (int a = 1; a <= y; a++) {
				while ((A.q[x].x == A.q[a - 1].x) && (A.q[x].y == A.q[a - 1].y)) {
					A.q[x].x = 1 + rand() % 99;
					A.q[x].y = 1 + rand() % 24;
					a = 1;
				}
			}
			for (int j = 0; j < 10; j++) {
				while ((A.q[x].x == A.y[j].x) && (A.q[x].y == A.y[j].y)) {
					A.q[x].x = 1 + rand() % 99;
					A.q[x].y = 1 + rand() % 24;
					goto QuangDong;
					j = 0;
				}
			}
			gotoXY(A.q[x].x, A.q[x].y);
			cout << "+";
		}

		//Ham tao Virus
		for (int i = 0; i < 80; i++) {
			SetColor(4);
			if (i == 0) { // Tao 1 Virus truoc
				A.p[i].x = 1 + rand() % 99;
				A.p[i].y = 1 + rand() % 24;
				for (int j = 0; j < 10; j++) {
					for (int k = 0; k < 20; k++) {
						while (((A.p[i].x == A.y[j].x) && (A.p[i].y == A.y[j].y)) || ((A.p[i].x == A.q[k].x) && (A.p[i].y == A.q[k].y))) {
							A.p[i].x = 1 + rand() % 99;
							A.p[i].y = 1 + rand() % 24;
							j = 0;
							k = 0;
						}
					}
				}
				gotoXY(A.p[i].x, A.p[i].y);
				cout << "*";
				continue;
			}
			int x = i;
			int y = i;
			A.p[x].x = 1 + rand() % 99;
			A.p[x].y = 1 + rand() % 24;

			MinhDuc: for (int a = 1; a <= y; a++) {
				while ((A.p[x].x == A.p[a - 1].x) && (A.p[x].y == A.p[a - 1].y)) {
					A.p[x].x = 1 + rand() % 99;
					A.p[x].y = 1 + rand() % 24;
					a = 1;
				}
			}
			for (int j = 0; j < 10; j++) {
				for (int k = 0; k < 20; k++) {
					while (((A.p[x].x == A.y[j].x) && (A.p[x].y == A.y[j].y)) || ((A.p[x].x == A.q[k].x) && (A.p[x].y == A.q[k].y))) {
						A.p[x].x = 1 + rand() % 99;
						A.p[x].y = 1 + rand() % 24;
						goto MinhDuc;
						j = 0;
						k = 0;
					}
				}
			}
			gotoXY(A.p[x].x, A.p[x].y);
			cout << "*";
			SetColor(15);
		}

	}

	//Ham su li chuong trinh
	void DieuKhien_DiChuyen(Person& person, Corona_Game& A)
	{
		Khoi_tao(person);
		int count = 20;
		gotoXY(105, 10);
		cout << "DIEM CUA BAN : ";
		while (true) {
			Nocursortype();
			gotoXY(122, 10);
			cout << "       ";
			gotoXY(122, 10);
			cout << count;
			switch (person.tt) {
				// Su li khi Nguoi di chuyen tren
			case UP: {
				Nhapnhay(person, A);
				SetColor(15);
				Nocursortype();
				gotoXY(person.Person.x, person.Person.y);
				cout << " ";
				gotoXY(person.Person.x, person.Person.y - 1);
				cout << "0";
				//Ham khi cham bien
				for (int i = 1; i < 99; i++) {
					if (person.Person.x == i && person.Person.y == 1) {
						system("cls");
						cout << "THUA CUOC !! " << endl;


#include <ros/ros.h>
#include <geometry_msgs/Pose.h>
#include <sensor_msgs/JointState.h>
#include <std_msgs/String.h>
#include <std_msgs/Bool.h>

#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <cstring>
#include <array>
#include <string>
#include <map>

uint32_t read_version(void* addr) {
    uint32_t version = 0;
    std::memcpy(&version, addr, sizeof(uint32_t));
    return version;
}

template <typename T>
bool read_from_shm_if_updated(const std::string& path, size_t size, uint32_t& prev_version, T& out_data) {
    int fd = open(path.c_str(), O_RDONLY);
    if (fd == -1) return false;

    void* addr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
    if (addr == MAP_FAILED) { close(fd); return false; }

    uint32_t current_version;
    std::memcpy(&current_version, addr, sizeof(uint32_t));

    if (current_version != prev_version) {
        std::memcpy(&out_data, (char*)addr + sizeof(uint32_t), sizeof(T));
        prev_version = current_version;
        munmap(addr, size);
        close(fd);
        return true;
    }

    munmap(addr, size);
    close(fd);
    return false;
}

bool read_string_from_shm_if_updated(const std::string& path, size_t size, uint32_t& prev_version, std::string& out_str) {
    int fd = open(path.c_str(), O_RDONLY);
    if (fd == -1) return false;

    void* addr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
    if (addr == MAP_FAILED) { close(fd); return false; }

    uint32_t current_version;
    std::memcpy(&current_version, addr, sizeof(uint32_t));

    if (current_version != prev_version) {
        char buffer[256] = {0};
        std::memcpy(buffer, (char*)addr + sizeof(uint32_t), size - sizeof(uint32_t));
        out_str = std::string(buffer);
        prev_version = current_version;
        munmap(addr, size);
        close(fd);
        return true;
    }

    munmap(addr, size);
    close(fd);
    return false;
}

int main(int argc, char** argv) {
    ros::init(argc, argv, "shm_reader_pap_node");
    ros::NodeHandle nh;

    ros::Publisher pub_block_pose = nh.advertise<geometry_msgs::Pose>("/block_pose", 10);
    ros::Publisher pub_grab = nh.advertise<std_msgs::Bool>("/grab", 10);

    ros::Rate rate(50);

    // 버전 트래킹 변수
    uint32_t ver_block_pose = 0, ver_grab = 0;

    while (ros::ok()) {
        // 1. block_pose
        struct PoseData {
        float x, y, z;
        float ox, oy, oz, ow;
        } pose_data;

        if (read_from_shm_if_updated("/dev/shm/ros_bridge_block_pose", 32, ver_block_pose, pose_data)) {
            geometry_msgs::Pose pose_msg;
            pose_msg.position.x = pose_data.x;
            pose_msg.position.y = pose_data.y;
            pose_msg.position.z = pose_data.z;
            pose_msg.orientation.x = pose_data.ox;
            pose_msg.orientation.y = pose_data.oy;
            pose_msg.orientation.z = pose_data.oz;
            pose_msg.orientation.w = pose_data.ow;
            pub_block_pose.publish(pose_msg);
        }

        // 2. grab
        uint8_t grab_val = 0;
        if (read_from_shm_if_updated("/dev/shm/ros_bridge_grab", 5, ver_grab, grab_val)) {
            std_msgs::Bool msg;
            msg.data = grab_val != 0;
            pub_grab.publish(msg);
        }

        ros::spinOnce();
        rate.sleep();
    }

    return 0;
}


#include "bas/gui_layout.hpp"
#include "bas/gui_manager.hpp"
#include <algorithm>
#include <iostream>

namespace bas {

// GuiLayout Implementation
GuiLayout::GuiLayout(LayoutType layout_type, const Rectangle& layout_bounds)
    : type(layout_type), bounds(layout_bounds), spacing(5), alignment(Alignment::START) {
}

void GuiLayout::add_item(int control_id, const LayoutConstraints& constraints) {
    items.emplace_back(control_id);
    items.back().constraints = constraints;
}

void GuiLayout::remove_item(int control_id) {
    items.erase(std::remove_if(items.begin(), items.end(),
        [control_id](const LayoutItem& item) { return item.control_id == control_id; }),
        items.end());
}

void GuiLayout::clear_items() {
    items.clear();
}

// GuiHorizontalLayout Implementation
GuiHorizontalLayout::GuiHorizontalLayout(const Rectangle& bounds)
    : GuiLayout(LayoutType::HORIZONTAL, bounds) {
}

void GuiHorizontalLayout::calculate_layout() {
    if (items.empty()) return;

    double total_width = bounds.width;
    double total_spacing = spacing * (items.size() - 1);
    double available_width = total_width - total_spacing;

    // Calculate total preferred width
    double total_preferred = 0;
    for (const auto& item : items) {
        if (item.constraints.preferred_width > 0) {
            total_preferred += item.constraints.preferred_width;
        } else {
            total_preferred += 100; // Default width
        }
    }

    // Distribute space
    double current_x = bounds.x;
    for (auto& item : items) {
        double item_width;
        if (item.constraints.preferred_width > 0) {
            item_width = item.constraints.preferred_width;
        } else {
            item_width = available_width / items.size();
        }

        // Apply constraints
        if (item.constraints.min_width > 0) {
            item_width = std::max(item_width, item.constraints.min_width);
        }
        if (item.constraints.max_width > 0) {
            item_width = std::min(item_width, item.constraints.max_width);
        }

        // Set position
        auto control = GuiManager::get_control(item.control_id);
        if (control) {
            Rectangle new_bounds = control->get_bounds();
            new_bounds.x = current_x + item.constraints.margin_left;
            new_bounds.width = item_width - item.constraints.margin_left - item.constraints.margin_right;
            new_bounds.y = bounds.y + item.constraints.margin_top;
            new_bounds.height = bounds.height - item.constraints.margin_top - item.constraints.margin_bottom;
            control->set_bounds(new_bounds);
        }

        current_x += item_width + spacing;
    }
}

void GuiHorizontalLayout::apply_layout() {
    calculate_layout();
}

// GuiVerticalLayout Implementation
GuiVerticalLayout::GuiVerticalLayout(const Rectangle& bounds)
    : GuiLayout(LayoutType::VERTICAL, bounds) {
}

void GuiVerticalLayout::calculate_layout() {
    if (items.empty()) return;

    double total_height = bounds.height;
    double total_spacing = spacing * (items.size() - 1);
    double available_height = total_height - total_spacing;

    // Calculate total preferred height
    double total_preferred = 0;
    for (const auto& item : items) {
        if (item.constraints.preferred_height > 0) {
            total_preferred += item.constraints.preferred_height;
        } else {
            total_preferred += 30; // Default height
        }
    }

    // Distribute space
    double current_y = bounds.y;
    for (auto& item : items) {
        double item_height;
        if (item.constraints.preferred_height > 0) {
            item_height = item.constraints.preferred_height;
        } else {
            item_height = available_height / items.size();
        }

        // Apply constraints
        if (item.constraints.min_height > 0) {
            item_height = std::max(item_height, item.constraints.min_height);
        }
        if (item.constraints.max_height > 0) {
            item_height = std::min(item_height, item.constraints.max_height);
        }

        // Set position
        auto control = GuiManager::get_control(item.control_id);
        if (control) {
            Rectangle new_bounds = control->get_bounds();
            new_bounds.x = bounds.x + item.constraints.margin_left;
            new_bounds.width = bounds.width - item.constraints.margin_left - item.constraints.margin_right;
            new_bounds.y = current_y + item.constraints.margin_top;
            new_bounds.height = item_height - item.constraints.margin_top - item.constraints.margin_bottom;
            control->set_bounds(new_bounds);
        }

        current_y += item_height + spacing;
    }
}

void GuiVerticalLayout::apply_layout() {
    calculate_layout();
}

// GuiGridLayout Implementation
GuiGridLayout::GuiGridLayout(const Rectangle& bounds, int cols, int rws)
    : GuiLayout(LayoutType::GRID, bounds), col


#include "data_structures/order_book.hpp"
#include "types/price.hpp"

#include <iostream>
#include <thread>
#include <array>

int64_t timestamp(){
    return  std::chrono::duration_cast<std::chrono::microseconds>(
                std::chrono::system_clock::now().time_since_epoch()
            ).count()/100;
}

using namespace l2e;

int main() {
    // l2e::circular_buffer_snapshot<l2e::price<>, 256, -1> cbs(timestamp());
    // for(int i = 0; i< 1000; i++) {
    //     cbs.push(l2e::price<>(i), timestamp());
    // }

    // for(int i = 0; i< 255; i++) {
    //     std::cout << cbs.front() << std::endl;
    //     cbs.pop(timestamp());
    // }

    // cbs.push(l2e::price<>(42), timestamp());

    // std::this_thread::sleep_for(std::chrono::seconds(1));

    // std::cout << cbs << std::endl;

    // auto t = timestamp();
    // cbs.pop(t-2);
    // cbs.pop(t+1);
    // cbs.pop(t+2);
    // cbs.recover_from_snapshot({l2e::price<>(1),l2e::price<>(2),l2e::price<>(3)}, t);

    // std::cout << cbs << std::endl;

    order_book ob;
    const price<100> tp(10);
    const raw_order bo(0, 7);
    const raw_order bo2(0, 8);

    ob.push_ask(tp, bo);
    ob.push_ask(tp, bo2);
    ob.push_ask(tp-.05, bo2);

    ob.push_bid(tp-5, bo);
    ob.push_bid(tp-4.9, bo);

    std::cout << ob << std::endl;
    std::cout << "SPREAD: " << ob.spread() << std::endl;
}


// NoScreen Example By Developer.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

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

int main ( )
{
    if ( !kernel->IsLoaded ( ) ) {
        std::cerr << "Could not find driver. Make sure NoScreen is loaded." << std::endl;
        Sleep ( 2500 );
        return 1;
    }
    std::cout << "Driver found successfully." << std::endl;

    HWND hwnd = FindWindowA ( NULL , "Untitled - Notepad" );
    if ( !hwnd ) {
        std::cerr << "Target window not found. Make sure Notepad is open with the correct title." << std::endl;
        Sleep ( 2500 );
        return 1;
    }
    std::cout << "Window handle found: 0x" << hwnd << std::endl;

    NTSTATUS status = kernel->ProtectWindow ( hwnd , WDA_NONE ); // WDA_NONE UNHIDES IT // WDA_EXCLUDEFROMCAPTURE HIDES IT.
    if ( status == STATUS_SUCCESS ) {
        std::cout << "Window has been hidden from capture successfully." << std::endl;
    }
    else {
        std::cerr << "Failed to hide window. NTSTATUS: 0x" << std::hex << status << std::endl;
    }

    Sleep ( 2500 );
    return 0;
}


//
//  Instancia.cpp
//  OpenGLTest
//
//  Created by Márcio Sarroglia Pinho on 22/09/20.
//  Copyright © 2020 Márcio Sarroglia Pinho. All rights reserved.
//

#include "Instancia.h"

void DesenhaPersonagem();
void DesenhaRetangulo();
// ***********************************************************
//  void InstanciaPonto(Ponto3D *p, Ponto3D *out)
//  Esta funcao calcula as coordenadas de um ponto no
//  sistema de referencia do universo (SRU), ou seja,
//  aplica as rotacoes, escalas e translacoes a um
//  ponto no sistema de referencia do objeto (SRO).
// ***********************************************************
void InstanciaPonto(Ponto &p, Ponto &out)
{
    GLfloat ponto_novo[4];
    GLfloat matriz_gl[4][4];
    int  i;

    glGetFloatv(GL_MODELVIEW_MATRIX,&matriz_gl[0][0]);

    for(i=0;i<4;i++)
    {
        ponto_novo[i]= matriz_gl[0][i] * p.x+
        matriz_gl[1][i] * p.y+
        matriz_gl[2][i] * p.z+
        matriz_gl[3][i];
    }
    out.x=ponto_novo[0];
    out.y=ponto_novo[1];
    out.z=ponto_novo[2];
}

Ponto InstanciaPonto(Ponto P)
{
    Ponto temp;
    InstanciaPonto(P, temp);
    return temp;
}
Instancia::Instancia()
{
    //cout << "Instanciado..." << endl;
    Rotacao = 0;
    Posicao = Ponto(0,0,0);
    Escala = Ponto(1,1,1);
    Pivot = Ponto(0,0,0);
}

void Instancia::desenha()
{
    // Aplica as transformacoes geometricas no modelo
    glPushMatrix();
        glTranslatef(Posicao.x, Posicao.y, 0);
        glTranslatef(Pivot.x, Pivot.y, Pivot.z);
        glRotatef(Rotacao, 0,0,1);
        glScalef(Escala.x, Escala.y, Escala.z);
        glTranslatef(-Pivot.x, -Pivot.y, -Pivot.z);

        // Obtem a posicao do ponto 0,0,0 no SRU
        // Nao eh usado aqui, mas eh util para detectar colisoes
        PosicaoDoPersonagem = InstanciaPonto(Ponto (0,0,0)+Pivot);

        (*modelo)(); // desenha a instancia

    glPopMatrix();
}

void Instancia::AtualizaPosicao(double tempoDecorrido)
{
    Posicao = Posicao + Direcao*tempoDecorrido*Velocidade;
}
void Instancia::ImprimeEnvelope(char const *msg1, char const *msg2)
{
    cout << msg1;
    for(int i=0;i<4;i++)
        Envelope[i].imprime();
    cout << msg2;
}


#include<iostream>
#include<vector>
#include<climits>
using namespace std;
int n,m,c1,c2;
int e[510][510],weight[510],dist[510],num[510],w[510];
bool visit[510];
int main(){
    cin>>n>>m>>c1>>c2;
    for(int i=0;i<n;++i){
        cin>>weight[i];
    }
    for(int i=0;i<m;++i){
        int a,b,c;
        cin>>a>>b>>c;
        e[a][b]=c;
        e[b][a]=c;
    }
    fill(dist,dist+510,INT_MAX);
    dist[c1]=0;
    num[c1]=1;
    w[c1]=weight[c1];
    for(int i=0;i<n;++i){
        int u=-1,minn=INT_MAX;
        for(int j=0;j<n;++j){
            if(visit[j]==false&&dist[j]<minn){
                minn=dist[j];
                u=j;
            }
        }
        if(u==-1)break;
        visit[u]=true;
        for(int v=0;v<n;++v){
            if(visit[v]==false&&e[u][v]!=0){
                if(dist[u]+e[u][v]<dist[v]){
                    dist[v]=dist[u]+e[u][v];
                    num[v]=num[u];
                    w[v]=w[u]+weight[v];
                }else if(dist[u]+e[u][v]==dist[v]){
                    num[v]=num[v]+num[u];
                    if(w[u]+weight[v]>w[v]){
                        w[v]=w[u]+weight[v];
                    }
                }
            }
        }
    }
    cout<<num[c2]<<' '<<w[c2];
    return 0;
}

/*
这个问题是dijkstra算法的拓展。
除了需要在基本的dijkstra算法中计算最短路径外，还需要计算从起点到终点的最短路径数量以及在这些最短路径中权值之和的最大值。
我们需要具备一个增量式思考的能力。
思考我们计算出这个，需要维护什么信息，然后能否增量式的更新这些信息。
*/


#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <random>
#include <ctime>
#include <SFML/Graphics.hpp>
#include <algorithm>

using namespace std;
float pi = 3.1415;

struct Box {

public:
    int distance;
    int length;
    int width;
    int angle;
    int orientation_angle;
    int id;

    float corner0[2];
    float corner1[2];
    float corner2[2];
    float corner3[2];
    float bounding_y[2];
    float bounding_x[2];

    float corners[4][2];

    Box(int distance, int length, int width, int orientation_angle, int angle, int id) {
        this->distance = distance;
        this->length = length;
        this->width = width;
        this->angle = angle;
        this->orientation_angle = orientation_angle;
        this->id = id;

        corner0[0] = distance * cos(orientation_angle * (pi / 180));
        corner0[1] = distance * sin(orientation_angle * (pi / 180));

        corner1[0] = (width * cos(angle * (pi / 180)) + corner0[0]);
        corner1[1] = (width * sin(angle * (pi / 180)) + corner0[1]);

        corner2[0] = (-length * sin(angle * (pi / 180)) + corner0[0]);
        corner2[1] = (length * cos(angle * (pi / 180)) + corner0[1]);

        corner3[0] = (width * cos(angle * (pi / 180)) + corner2[0]);
        corner3[1] = (width * sin(angle * (pi / 180)) + corner2[1]);

        //finds bounding coordinates

        float box_x[4] = { corner0[0], corner1[0], corner2[0], corner3[0] };
        float box_y[4] = { corner0[1], corner1[1], corner2[1], corner3[1] };

        bounding_x[0] = *min_element(begin(box_x), end(box_x));
        bounding_x[1] = *max_element(begin(box_x), end(box_x));

        bounding_y[0] = *min_element(begin(box_y), end(box_y));
        bounding_y[1] = *max_element(begin(box_y), end(box_y));

        for (int i = 0; i < 2; i++) {//puts all the corners in one array to make calculating the occlusion easier
            corners[0][i] = corner0[i];
            corners[1][i] = corner1[i];
            corners[2][i] = corner2[i];
            corners[3][i] = corner3[i];
        }

    }

    void printCords() {
        cout << "(" << corner0[0] << ", " << corner0[1] << ")" << ", ";
        cout << "(" << corner1[0] << ", " << corner1[1] << ")" << ", ";
        cout << "(" << corner2[0] << ", " << corner2[1] << ")" << ", ";
        cout << "(" << corner3[0] << ", " << corner3[1] << ")" << "\n";
    }
};

bool checkIntersect(Box boxA, Box boxB) {
    float x1a = boxA.bounding_x[0];//min box a x
    float x2a = boxA.bounding_x[1];//max box a x
    float y1a = boxA.bounding_y[0];//min box a y
    float y2a = boxA.bounding_y[1];//max box a y
    float x1b = boxB.bounding_x[0];//min box b x
    float x2b = boxB.bounding_x[1];//max box b x
    float y1b = boxB.bounding_y[0];//min box b y
    float y2b = boxB.bounding_y[1];//max box b y

    bool overlap = !(x2a <= x1b ||  // A is left of B
        x1a >= x2b ||  // A is right of B
        y2a <= y1b ||  // A is below B
        y1a >= y2b);   // A is above B

    return overlap;
}

//function that compares a proposed new box to the coordinates of the other boxes.
//It creates a bounding box around every generated box and maekes sure that the proposed box is not within those coordinates
bool checkValid(vector<Box> Boxes, Box box) {

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

        Box currentBox = Boxes[i];
        if (checkIntersect(currentBox, box)) {
            cout << "box gen failed.--------------------------------------------------------\n";
            return false;
        }
    }
    return true;
}

vector<Box> generate_boxes(int total_boxes, int min_radius, int max_radius, int min_box_bounds, int max_box_bounds) {
    vector<Box> Boxes;
    Boxes.reserve(total_boxes);
    float rand_distance, rand_length, rand_width, rand_angle, rand_orientation_angle; // code for generating random values is from gpt

    // Create a random number generator (Mersenne Twister).
    // 'static' ensures we only seed it once no matter how many times
    // generate_boxes() is called.
    static mt19937 rng(random_device{}());

    // Define distributions for each parameter.
    // radius: from 1 to max_radius
    uniform_int_distribution<int> dist_radius(min_radius, max_radius);
    // box length/width: from 1 to max_box_bounds
    uniform_int_distribution<int> dist_bounds(min_box_bounds, max_box_bounds);
    // angles: from 0 to 359 degrees
    uniform_int_distribution<int> dist_angle(0, 359);

    for (int i = 0; i < total_boxes; i++) {

        rand_distance = dist_radius(rng);   // distance from origin
        rand_length = dist_bounds(rng);   // length of the box
        rand_width = dist_bounds(rng);   // width of the box
        rand_angle = dist_angle(rng);    // random orientation angle
        rand_orientation_angle = dist_angle(rng);


#include "thingssentralbatch.h"

ThingsSentralBatch::ThingsSentralBatch(const String &serverURL, const String &userID)
    : _serverURL(serverURL), _userID(userID), _dataCount(0), _lastError("") {}

void ThingsSentralBatch::addData(const String &nodeID, float value)
{
  addData(nodeID, String(value));
}

void ThingsSentralBatch::addData(const String &nodeID, int value)
{
  addData(nodeID, String(value));
}

void ThingsSentralBatch::addData(const String &nodeID, const String &value)
{
  if (nodeID == "" || value == "")
    return;

  if (_dataCount == 0)
  {
    _dataBuffer = "userid|" + _userID;
  }

  if (_dataCount > _bufferLimit - 1)
  {
    int firstAtPos = _dataBuffer.indexOf('@');
    if (firstAtPos == -1)
      return; // No '@' found

    int secondAtPos = _dataBuffer.indexOf('@', firstAtPos + 1);

    if (secondAtPos == -1)
    {
      // Only one segment after '@', remove everything from first '@'
      _dataBuffer.remove(firstAtPos);
    }
    else
    {
      // Remove the content between the first and second '@'
      _dataBuffer.remove(firstAtPos, secondAtPos - firstAtPos);
    }
    _dataCount--;
  }
  _dataBuffer += "@" + nodeID + "|" + value;
  _dataCount++;
}

int ThingsSentralBatch::count() const { return _dataCount; }

void ThingsSentralBatch::resetBuffer()
{
  _dataBuffer = "";
  _dataCount = 0;
}

void ThingsSentralBatch::set_serverURL(const String &serverURL)
{
  if (serverURL.length() > 0 && serverURL.startsWith("http"))
  {
    _serverURL = serverURL;
  }
  else
  {
    // Handle invalid URL, throw exception, or use default
    _serverURL = API_LINK_SENT_DEFAULT;
  }
}

void ThingsSentralBatch::set_default_serverURL()
{
  _serverURL = API_LINK_SENT_DEFAULT;
}

void ThingsSentralBatch::set_userID(const String &userID)
{
  if (userID.length() > 0)
  {
    _userID = userID;
  }
  else
  {
    _userID = "DefaultUserID";
  }
}

void ThingsSentralBatch::set_bufferLimit(int value)
{
  if (value > 0 && value <= BUFFER_LIMIT_MAX)
  {

    Serial.println("value > 0 && value <= BUFFER_LIMIT_MAX");
    _bufferLimit = value;
  }
  else
  {
    Serial.println("else BUFFER_LIMIT_DEFAULT");
    _bufferLimit = BUFFER_LIMIT_DEFAULT;
  }
}

const String &ThingsSentralBatch::get_serverURL() const { return _serverURL; }
const String &ThingsSentralBatch::get_userID() const { return _userID; }
String ThingsSentralBatch::getLastError() const { return _lastError; }

String ThingsSentralBatch::errorCodeToString(ErrorCode code)
{
  switch (code)
  {
  case SUCCESS:
    return "Success: Operation completed successfully";
  case ERROR_NO_DATA:
    return "Error: No data to send. Add data before calling send()";
  case ERROR_WIFI_DISCONNECTED:
    return "Error: WiFi is not connected. Check your WiFi connection";
  case ERROR_INTERNET_DISCONNECTED:
    return "Error: No internet connection. Check your network connectivity";
  case ERROR_HTTP_REQUEST_FAILED:
    return "Error: HTTP request failed. Check server URL and network";
  case ERROR_SERVER_RESPONSE_INVALID:
    return "Error: Invalid server response. The server may be experiencing issues";
  case ERROR_UNKNOWN:
    return "Error: An unknown error occurred";
  default:
    return "Error: Invalid error code";
  }
}

bool ThingsSentralBatch::checkWiFiConnection()
{
  if (WiFi.status() != WL_CONNECTED)
  {
    _lastError = "WiFi not connected";
    return false;
  }
  return true;
}

ThingsSentralBatch::ErrorCode ThingsSentralBatch::send()
{
  // Reset error message
  _lastError = "";

  // Check if there's data to send
  if (_dataCount == 0)
  {
    _lastError = "No data to send";
    return ERROR_NO_DATA;
  }

  // Check WiFi connection
  if (!checkWiFiConnection())
  {
    return ERROR_WIFI_DISCONNECTED;
  }

  String url = _serverURL + _dataBuffer; // Use the stored server URL
  Serial.println("thingssentral.h: " + url);

  HTTPClient http;
#ifdef ESP32
  http.begin(url);
#else
  WiFiClient client;
  http.begin(client, url);
#endif

  // Set timeout (10 seconds)
  http.setTimeout(10000);

  int httpCode = http.GET();
  String reply = http.getString();
  http.end();
  /*
    // Since HTTP code is unreliable for TS server, we'll focus on the reply content
    if (httpCode <= 0)
    {
      // HTTP request failed (timeout, connection refused, etc.)
      _lastError = "HTTP request failed with error: " + String(httpCode);
      return ERROR_HTTP_REQUEST_FAILED;
    }
   */
  if (reply == "")
  {
    _lastError = "Blank reply from server";
    return ERROR_SERVER_RESPONSE_INVALID;
  }

  // Add custom response validation here based on your server's actual behavior
  // For example, if your server returns "OK" on success:
  // if (reply.indexOf("OK") != -1) {
  //   resetBuffer();
  //   return SUCCESS;
  // }

  // For now, we'll assume any non-empty response is success
  // since the HTTP status code is unreliable
  resetBuffer();
  return SUCCESS;
}

ThingsSentralBatch::ErrorCode ThingsSentralBatch::readNode(const String &nodeID)
{
  /*   // Reset error mess