#include "UIClass.h"

UIClass::UIClass(
    OledDisplayClass* display,
    ButtonClass* buttonMinus,
    ButtonClass* buttonPlus,
    ButtonClass* buttonEnter,
    Sht40Class* sht40,
    MqttClass* mqtt,
    TempControlClass* tempControl,
    const char** roomNames,
    int roomsCount,
    int defaultRoom
)
{
    _display = display;
    _buttonMinus = buttonMinus;
    _buttonPlus = buttonPlus;
    _buttonEnter = buttonEnter;
    _sht40 = sht40;
    _mqtt = mqtt;
    _tempControl = tempControl;

    _roomsCount = roomsCount;

    _roomNames = roomNames;
    _defaultRoom = defaultRoom;
    _currentRoom = defaultRoom;

    _drawSettings = false;
}

UIClass::~UIClass() {}

void UIClass::DrawActTime(int timeHH, int timeMM)
{
    String str = TimeFormater(timeHH) + ":" + TimeFormater(timeMM);
    _display->string(111, 3, str, FONT_10, TEXT_RIGHT);
}

void UIClass::DrawConnectionStatus(bool online)
{
    if(online)
    {
        for(int i = 0; i < sizeof(_iconOnlineX); i++)
        {
            _display->pixel(114 + _iconOnlineX[i], 6 + _iconOnlineY[i]);
        }
    }
    else
    {
        for(int i = 0; i < sizeof(_iconOfflineX); i++){
            _display->pixel(114 + _iconOfflineX[i], 6 + _iconOfflineY[i]);
        }
    }
}

void UIClass::DrawHeatingDisabled()
{
    for(int i = 0; i < sizeof(_iconDisabledX); i++)
    {
        _display->pixel(3 + _iconDisabledX[i], 50 + _iconDisabledY[i]);
    }
}

void UIClass::DrawRelayState(int relay)
{
    if(relay == 1)
    {
        for(int i = 0; i < sizeof(_iconRelayOnX); i++) {
            _display->pixel(60 + _iconRelayOnX[i], 50 + _iconRelayOnY[i]);
        }
    }
}

void UIClass::DrawRoomName(int roomNumber)
{
    String str = _roomNames[roomNumber];
    _display->string(3, 3, str);
}

void UIClass::DrawMainTemperature(float temp)
{
    _display->string(84, 17, String(temp, 1), FONT_24, TEXT_RIGHT);
    _display->string(86, 19, "°C", FONT_10, TEXT_LEFT);
}

void UIClass::DrawSecondaryTemperature(float temp)
{
    _display->string(3, 47, String(temp,1) + "°C");
}

void UIClass::DrawHumidity(int humidity)
{
    _display->string(125, 47, String(humidity) + "%rH", TEXT_RIGHT);
}

void UIClass::DrawCurrentRoomHeatingOn()
{
    _display->clear();
    DrawActTime(_timeHH, _timeMM);
    DrawConnectionStatus(_mqtt->getConnected());
    DrawRoomName(_currentRoom);
    if(_currentRoom != 4)
    {
        DrawRelayState(_tempControl->getRelays(_currentRoom));
        DrawMainTemperature(_tempControl->getTempSet(_currentRoom));
        DrawSecondaryTemperature(_tempControl->getTempAct(_currentRoom));
    }
    else
    {
        DrawMainTemperature(_tempControl->getTempAct(_currentRoom));
    }
    DrawHumidity(_tempControl->getHumidity(_currentRoom));
    _display->display();
}

void UIClass::DrawCurrentRoomHeatingOff()
{
    _display->clear();
    DrawActTime(_timeHH, _timeMM);
    DrawConnectionStatus(_mqtt->getConnected());
    DrawHeatingDisabled();
    DrawRoomName(_currentRoom);
    DrawMainTemperature(_tempControl->getTempAct(_currentRoom));
    DrawHumidity(_tempControl->getHumidity(_currentRoom));
    _display->display();
}

void UIClass::DrawSettings()
{
    _display->clear();
    _display->string(1, 1, "Nastaveni");
    String strPage = String(_settingsCurrentPage + 1) + "/" + String(_settingsPages);
    _display->string(126, 1, strPage, TEXT_RIGHT);

    if(_settingsArrowY[_settingsCurrentPage][_settingsCurrentRow] != -1)
        _display->string(1, _settingsArrowY[_settingsCurrentPage][_settingsCurrentRow] + 1, "->");

    if(_settingsCurrentPage == 0)
    {
        _display->string(11, 11, "Topeni:");
        if(_tempControl->getHeatingEnabled())
            _display->string(126, 11, "zapnuto", TEXT_RIGHT);
        else
            _display->string(126, 11, "vypnuto", TEXT_RIGHT);

        _display->string(1, 21, "Regulace:");

        String strSensPlus = String(_tempControl->getTempControlSensPlus(), 1) + "°C";
        _display->string(11, 31, "Citlivost +:");
        _display->string(126, 31, strSensPlus, TEXT_RIGHT);

        String strSensMinus = "-" + String(_tempControl->getTempControlSensMinus(), 1) + "°C";
        _display->string(11, 41, "Citlivost -:");
        _display->string(126, 41, strSensMinus, TEXT_RIGHT);

        String strInterval = String(_tempControl->getTempControlIntervalMinutes()) + "min";
        _display->string(11, 51, "Frekvence:");
        _display->string(126, 51, strInterval, TEXT_RIGHT);
    }
    else if(_settingsCurrentPage == 1)
    {
        _display->string(1, 11, "Detekce vetrani:");

        String strDiff = "-" + String(_tempControl->getTempControlDifference(), 1) + "°C";
        _display->string(11, 21, "Pokles o:");
        _display->string(126, 21, strDiff, TEXT_RIGHT);

        _display->string(1, 31, "Teplot. koef. rele:");

        String strRelayOn = String(_tempControl->getRelayTempCoefOn(), 2);
        _display->string(11, 41, "Pri sepnuti:");
        _display->string(126, 41, strRelayOn,


#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/string_cast.hpp>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#include <iostream>
#include <array>

float fov = 45.0f;
float pitch = 0.0f, yaw = -90.0f;
float x_last_time = 800.0f / 2.0f, y_last_time = 600.0f / 2.0f;
bool is_front_locked = true;
glm::vec3 camera_front_direction = glm::vec3(0.0f, 0.0f, -1.0f);

std::ostream& operator<<(std::ostream& out, const glm::vec3& g)
{
	return out << glm::to_string(g);
}

std::ostream& operator<<(std::ostream& out, const glm::mat4& g)
{
	return out << glm::to_string(g);
}

void ScrollCallback(GLFWwindow* window, double x_offset, double y_offset)
{
	if (fov >= 5.0f && fov <= 90.0f)
	{
		fov -= y_offset;
	}
	else if (fov <= 5.0f)
	{
		fov = 5.0f;
	}
	else // (fov >= 90.0f)
	{
		fov = 90.0f;
	}
}

void KeyboardCallback(GLFWwindow* window, glm::vec3* camera_position, const glm::vec3& camera_front, const glm::vec3& camera_up, const float delta_time_between_frames)
{
	if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS)
	{
		is_front_locked = !is_front_locked;
	}
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
	{
		glfwSetWindowShouldClose(window, true);
	}
	float camera_speed = 2.0f * delta_time_between_frames;
	if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
	{
		*camera_position += camera_speed * camera_front;
	}
	if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
	{
		*camera_position -= camera_speed * camera_front;
	}
	if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
	{
		*camera_position -= glm::normalize(glm::cross(camera_front, camera_up)) * camera_speed;
	}
	if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
	{
		*camera_position += glm::normalize(glm::cross(camera_front, camera_up)) * camera_speed;
	}
}

void MouseCallback(GLFWwindow* window, double in_x_pos, double in_y_pos)
{
	float x_pos = static_cast<float>(in_x_pos);
	float y_pos = static_cast<float>(in_y_pos);

	if (is_front_locked)
	{
		x_last_time = x_pos;
		y_last_time = y_pos;
	}

	float x_offset = x_pos - x_last_time;
	float y_offset = y_last_time - y_pos; // reversed since y-coordinates go from bottom to top
	x_last_time = x_pos;
	y_last_time = y_pos;

	float sensitivity = 0.3f;
	x_offset *= sensitivity;
	y_offset *= sensitivity;
	yaw += x_offset;
	pitch += y_offset;
	if (pitch > 89.0f)
		pitch = 89.0f;
	if (pitch < -89.0f)
		pitch = -89.0f;
	glm::vec3 current_front;
	current_front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
	current_front.y = sin(glm::radians(pitch));
	current_front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
	camera_front_direction = glm::normalize(current_front);
}

void FramebufferSizeCallback(GLFWwindow*, int width, int height)
{
	glViewport(0, 0, width, height);
}

void SetCallbackAndLoadGlad(GLFWwindow* window)
{
	if (window == NULL)
	{
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		std::exit(EXIT_FAILURE);
	}
	glfwMakeContextCurrent(window);
	glfwSetFramebufferSizeCallback(window, FramebufferSizeCallback);
	glfwSetCursorPosCallback(window, MouseCallback);
	glfwSetScrollCallback(window, ScrollCallback);
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cout << "Failed to initialize GLAD" << std::endl;
		std::exit(EXIT_FAILURE);
	}
	glEnable(GL_DEPTH_TEST);
}

unsigned int LinkToShaderProgram(unsigned int vertex_shader, unsigned int fragment_shader)
{
	int success = 1;
	char info_log[512];
	glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
	if (success == 0)
	{
		glGetShaderInfoLog(vertex_shader, 512, NULL, info_log);
		std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << info_log << std::endl;
		success = 1;
		memset(info_log, 0, sizeof(info_log));
	}
	glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
	if (success == 0)
	{
		glGetShaderInfoLog(fragment_shader, 512, NULL, info_log);
		std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << info_log << std::endl;
		success = 1;
		memset(info_log, 0, sizeof(info_log));
	}
	unsigned int shader_program = glCreateProgram();
	glAttachShader(shader_program, vertex_shader);
	glAttachShader(shader_program, fragment_shader);
	glLinkProgram(shader_program);
	glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
	if (success == 0)
	{
		glGetProgramInfoLog(shader_program, 512, NULL, info_log);
		std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << info_log << std::endl;
	}
	glDeleteShader(vertex_shader);
	glDeleteShader(fragment_shader);
	return shader_program;
}

unsigned int BuildShaderProgram()
{
	unsigned int vertex_shader, fragment_shader;
	const char* vertex_shader_script = R"(
		#version 330 core
		layout (location = 0) in vec3 orig_pos;
		layout (location = 4) in vec2 orig_tex_coord;
		out vec2 inter_tex_coord;

		uniform mat4 model;
		uniform mat4 view;
		uniform mat4 projection;

		void main() {
			gl_Position = projection * view * model *


#include "KawaiiPhysicsEditMode.h"
#include "SceneManagement.h"
#include "EngineUtils.h"
#include "IPersonaPreviewScene.h"
#include "Animation/DebugSkelMeshComponent.h"
#include "EditorModeManager.h"
#include "CanvasItem.h"
#include "CanvasTypes.h"
#include "Materials/MaterialInstanceDynamic.h"
#include "AnimationRuntime.h"
#include "KawaiiPhysicsLimitsDataAsset.h"

#define LOCTEXT_NAMESPACE "KawaiiPhysicsEditMode"

struct HKawaiiPhysicsHitProxy : public HHitProxy
{
	DECLARE_HIT_PROXY()

	HKawaiiPhysicsHitProxy(ECollisionLimitType InType, int32 InIndex, bool InFromDataAsset = false)
		: HHitProxy(HPP_Wireframe)
		, CollisionType(InType)
		, CollisionIndex(InIndex)
		, bFromDataAsset(InFromDataAsset)
	{
	}

	virtual EMouseCursor::Type GetMouseCursor() override
	{
		return EMouseCursor::Crosshairs;
	}

	ECollisionLimitType CollisionType;
	int32 CollisionIndex;
	bool bFromDataAsset;
};
IMPLEMENT_HIT_PROXY(HKawaiiPhysicsHitProxy, HHitProxy);

FKawaiiPhysicsEditMode::FKawaiiPhysicsEditMode()
	: RuntimeNode(nullptr)
	, GraphNode(nullptr)
	, SelectCollisionIsFromDataAsset(false)
	, CurWidgetMode(UE_WIDGET::EWidgetMode::WM_Translate)
{
}

void FKawaiiPhysicsEditMode::EnterMode(UAnimGraphNode_Base* InEditorNode, FAnimNode_Base* InRuntimeNode)
{
	RuntimeNode = static_cast<FAnimNode_KawaiiPhysics*>(InRuntimeNode);
	GraphNode = CastChecked<UAnimGraphNode_KawaiiPhysics>(InEditorNode);

	GraphNode->Node.SphericalLimitsData = RuntimeNode->SphericalLimitsData;
	GraphNode->Node.CapsuleLimitsData = RuntimeNode->CapsuleLimitsData;
	GraphNode->Node.PlanarLimitsData = RuntimeNode->PlanarLimitsData;

	NodePropertyDelegateHandle = GraphNode->OnNodePropertyChanged().AddSP(this, &FKawaiiPhysicsEditMode::OnExternalNodePropertyChange);

#if	ENGINE_MAJOR_VERSION == 5
	FAnimNodeEditMode::EnterMode(InEditorNode, InRuntimeNode);
#else
	FKawaiiPhysicsEditModeBase::EnterMode(InEditorNode, InRuntimeNode);
#endif

}

void FKawaiiPhysicsEditMode::ExitMode()
{
	GraphNode->OnNodePropertyChanged().Remove(NodePropertyDelegateHandle);

	GraphNode = nullptr;
	RuntimeNode = nullptr;

#if	ENGINE_MAJOR_VERSION == 5
	FAnimNodeEditMode::ExitMode();
#else
	FKawaiiPhysicsEditModeBase::ExitMode();
#endif

}

void FKawaiiPhysicsEditMode::Render(const FSceneView* View, FViewport* Viewport, FPrimitiveDrawInterface* PDI)
{
	const USkeletalMeshComponent* SkelMeshComp = GetAnimPreviewScene().GetPreviewMeshComponent();

#if	ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 1
	if (SkelMeshComp && SkelMeshComp->GetSkeletalMeshAsset() && SkelMeshComp->GetSkeletalMeshAsset()->GetSkeleton())
#else
	if (SkelMeshComp && SkelMeshComp->SkeletalMesh && SkelMeshComp->SkeletalMesh->Skeleton)
#endif
	{
		RenderSphericalLimits(PDI);
		RenderCapsuleLimit(PDI);
		RenderPlanerLimit(PDI);
		PDI->SetHitProxy(nullptr);

		if (IsValidSelectCollision())
		{
			FCollisionLimitBase* Collision = GetSelectCollisionLimitRuntime();
			if (Collision)
			{
				FTransform BoneTransform = FTransform::Identity;
				if (Collision->DrivingBone.BoneIndex >= 0)
				{
					BoneTransform = RuntimeNode->ForwardedPose.GetComponentSpaceTransform(
						Collision->DrivingBone.GetCompactPoseIndex(RuntimeNode->ForwardedPose.GetPose().GetBoneContainer()));
				}
				PDI->DrawPoint(BoneTransform.GetLocation(), FLinearColor::White, 10.0f, SDPG_Foreground);
				DrawDashedLine(PDI, Collision->Location, BoneTransform.GetLocation(),
					FLinearColor::White, 1, SDPG_Foreground);
				DrawCoordinateSystem(PDI, BoneTransform.GetLocation(), Collision->Rotation.Rotator(), 20, SDPG_World + 1);

			}
		}
	}

#if	ENGINE_MAJOR_VERSION == 5
	FAnimNodeEditMode::Render(View, Viewport, PDI);
#else
	FKawaiiPhysicsEditModeBase::Render(View, Viewport, PDI);
#endif

}

void FKawaiiPhysicsEditMode::RenderSphericalLimits(FPrimitiveDrawInterface* PDI) const
{
	if (GraphNode->bEnableDebugDrawSphereLimit)
	{
		for( int32 i=0; i< RuntimeNode->SphericalLimits.Num(); i++)
		{
			auto& Sphere = RuntimeNode->SphericalLimits[i];
			if (Sphere.bEnable && Sphere.Radius > 0)
			{
				PDI->SetHitProxy(new HKawaiiPhysicsHitProxy(ECollisionLimitType::Spherical, i));
				DrawSphere(PDI, Sphere.Location, FRotator::ZeroRotator, FVector(Sphere.Radius), 24, 6,
					GEngine->ConstraintLimitMaterialPrismatic->GetRenderProxy(), SDPG_World);
				DrawWireSphere(PDI, Sphere.Location, FLinearColor::Black, Sphere.Radius, 24, SDPG_World);
				DrawCoordinateSystem(PDI, Sphere.Location, Sphere.Rotation.Rotator(), Sphere.Radius, SDPG_World + 1);
			}
		}

		for (int32 i = 0; i < RuntimeNode->SphericalLimitsData.Num(); i++)
		{
			auto& Sphere = RuntimeNode->SphericalLimitsData[i];
			if (Sphere.bEnable && Sphere.Radius > 0)
			{
				PDI->SetHitProxy(new HKawaiiPhysicsHitProxy(ECollisionLimitType::Spherical, i, true));
				DrawSphere(PDI, Sphere.Location, FRotator::ZeroRotator, FVector(Sphere.Radius), 24, 6,
					GEngine->ConstraintLimitMaterialZ->GetRenderProxy(), SDPG_World);
				DrawWireSphere(PDI, Sphere.Location, FLinearColor::Black, Sphere.Radius, 24,


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

#include "Variant_Shooter/AI/ShooterNPC.h"
#include "ShooterWeapon.h"
#include "Components/SkeletalMeshComponent.h"
#include "Camera/CameraComponent.h"
#include "Kismet/KismetMathLibrary.h"
#include "Engine/World.h"
#include "ShooterGameMode.h"
#include "Components/CapsuleComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "TimerManager.h"

#include "StatConstants.h"

#include "SimpleGameStatsSubsystem.h"

void AShooterNPC::BeginPlay()
{
	Super::BeginPlay();

	// spawn the weapon
	FActorSpawnParameters SpawnParams;
	SpawnParams.Owner = this;
	SpawnParams.Instigator = this;
	SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;

	Weapon = GetWorld()->SpawnActor<AShooterWeapon>(WeaponClass, GetActorTransform(), SpawnParams);
}

void AShooterNPC::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	Super::EndPlay(EndPlayReason);

	// clear the death timer
	GetWorld()->GetTimerManager().ClearTimer(DeathTimer);
}

float AShooterNPC::TakeDamage(float Damage, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
	// ignore if already dead
	if (bIsDead)
	{
		return 0.0f;
	}

	// Reduce HP
	CurrentHP -= Damage;

	// Have we depleted HP?
	if (CurrentHP <= 0.0f)
	{
		Die();
	}

	return Damage;
}

void AShooterNPC::AttachWeaponMeshes(AShooterWeapon* WeaponToAttach)
{
	const FAttachmentTransformRules AttachmentRule(EAttachmentRule::SnapToTarget, false);

	// attach the weapon actor
	WeaponToAttach->AttachToActor(this, AttachmentRule);

	// attach the weapon meshes
	WeaponToAttach->GetFirstPersonMesh()->AttachToComponent(GetFirstPersonMesh(), AttachmentRule, FirstPersonWeaponSocket);
	WeaponToAttach->GetThirdPersonMesh()->AttachToComponent(GetMesh(), AttachmentRule, FirstPersonWeaponSocket);
}

void AShooterNPC::PlayFiringMontage(UAnimMontage* Montage)
{
	// unused
}

void AShooterNPC::AddWeaponRecoil(float Recoil)
{
	// unused
}

void AShooterNPC::UpdateWeaponHUD(int32 CurrentAmmo, int32 MagazineSize)
{
	// unused
}

FVector AShooterNPC::GetWeaponTargetLocation()
{
	// start aiming from the camera location
	const FVector AimSource = GetFirstPersonCameraComponent()->GetComponentLocation();

	FVector AimDir, AimTarget = FVector::ZeroVector;

	// do we have an aim target?
	if (CurrentAimTarget)
	{
		// target the actor location
		AimTarget = CurrentAimTarget->GetActorLocation();

		// apply a vertical offset to target head/feet
		AimTarget.Z += FMath::RandRange(MinAimOffsetZ, MaxAimOffsetZ);

		// get the aim direction and apply randomness in a cone
		AimDir = (AimTarget - AimSource).GetSafeNormal();
		AimDir = UKismetMathLibrary::RandomUnitVectorInConeInDegrees(AimDir, AimVarianceHalfAngle);

	} else {

		// no aim target, so just use the camera facing
		AimDir = UKismetMathLibrary::RandomUnitVectorInConeInDegrees(GetFirstPersonCameraComponent()->GetForwardVector(), AimVarianceHalfAngle);

	}

	// calculate the unobstructed aim target location
	AimTarget = AimSource + (AimDir * AimRange);

	// run a visibility trace to see if there's obstructions
	FHitResult OutHit;

	FCollisionQueryParams QueryParams;
	QueryParams.AddIgnoredActor(this);

	GetWorld()->LineTraceSingleByChannel(OutHit, AimSource, AimTarget, ECC_Visibility, QueryParams);

	// return either the impact point or the trace end
	return OutHit.bBlockingHit ? OutHit.ImpactPoint : OutHit.TraceEnd;
}

void AShooterNPC::AddWeaponClass(const TSubclassOf<AShooterWeapon>& InWeaponClass)
{
	// unused
}

void AShooterNPC::OnWeaponActivated(AShooterWeapon* InWeapon)
{
	// unused
}

void AShooterNPC::OnWeaponDeactivated(AShooterWeapon* InWeapon)
{
	// unused
}

void AShooterNPC::OnSemiWeaponRefire()
{
	// are we still shooting?
	if (bIsShooting)
	{
		// fire the weapon
		Weapon->StartFiring();
	}
}

void AShooterNPC::Die()
{
	// ignore if already dead
	if (bIsDead)
	{
		return;
	}

	// raise the dead flag
	bIsDead = true;

    // =======================
    // Get Subsystem From GameInstance
    // Track NPCs Killed: "Enemies Defeated"
    USimpleGameStatsSubsystem* StatsSubsystem = GetGameInstance()->GetSubsystem<USimpleGameStatsSubsystem>();
    if (IsValid(StatsSubsystem)) {
        StatsSubsystem->IncrementStat(UStatConstants::GetStatName_EnemiesDefeated());
    }
    // =======================

	// increment the team score
	if (AShooterGameMode* GM = Cast<AShooterGameMode>(GetWorld()->GetAuthGameMode()))
	{
		GM->IncrementTeamScore(TeamByte);
	}

	// disable capsule collision
	GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);

	// stop movement
	GetCharacterMovement()->StopMovementImmediately();
	GetCharacterMovement()->StopActiveMovement();

	// enable ragdoll physics on the third person mesh
	GetMesh()->SetCollisionProfileName(RagdollCollisionProfile);
	GetMesh()->SetSimulatePhysics(true);
	GetMesh()->SetPhysicsBlendWeight(1.0f);

	// schedule actor destruction
	GetWorld()->GetTime


#include "outetts.h"
#include <iostream>
#include <fstream>
#include <cstring>
#include <cmath>
#include <string>
#include <thread>
#include <vector>
#include <algorithm>
#include <regex>
#include <map>
#include "ggml.h"
#include "llama.h"
#include <common/common.h>  // 修正common.h的引入路径
#include <common/sampling.h>  // 修正sampling.h的引入路径

namespace edge {

struct wav_header {
    char riff[4] = {'R', 'I', 'F', 'F'};
    uint32_t chunk_size;
    char wave[4] = {'W', 'A', 'V', 'E'};
    char fmt[4] = {'f', 'm', 't', ' '};
    uint32_t fmt_chunk_size = 16;
    uint16_t audio_format = 1; // PCM
    uint16_t num_channels = 1; // Mono
    uint32_t sample_rate;
    uint32_t byte_rate;
    uint16_t block_align;
    uint16_t bits_per_sample = 16;
    char data[4] = {'d', 'a', 't', 'a'};
    uint32_t data_size;
};

// 数字到文字转换的映射
static const std::map<int, std::string> ones = {
    {0, "zero"}, {1, "one"}, {2, "two"}, {3, "three"}, {4, "four"},
    {5, "five"}, {6, "six"}, {7, "seven"}, {8, "eight"}, {9, "nine"},
    {10, "ten"}, {11, "eleven"}, {12, "twelve"}, {13, "thirteen"}, {14, "fourteen"},
    {15, "fifteen"}, {16, "sixteen"}, {17, "seventeen"}, {18, "eighteen"}, {19, "nineteen"}
};

static const std::map<int, std::string> tens = {
    {2, "twenty"}, {3, "thirty"}, {4, "forty"}, {5, "fifty"},
    {6, "sixty"}, {7, "seventy"}, {8, "eighty"}, {9, "ninety"}
};

static void fill_hann_window(int length, bool periodic, float * output) {
    for (int i = 0; i < length; i++) {
        output[i] = 0.5 * (1.0 - cos(2.0 * M_PI * i / (length - (periodic ? 1 : 0))));
    }
}

static void twiddle(float * real, float * imag, int k, int N) {
    float phi = -2.0 * M_PI * k / N;
    *real = cos(phi);
    *imag = sin(phi);
}

// 实现简单的傅立叶逆变换
static void irfft(int n, const float * inp_cplx, float * out_real) {
    int N = n / 2 + 1;

    std::vector<float> real_input(N);
    std::vector<float> imag_input(N);

    for (int i = 0; i < N; i++) {
        real_input[i] = inp_cplx[2*i];
        imag_input[i] = inp_cplx[2*i + 1];
    }

    std::vector<float> real_output(n);
    std::vector<float> imag_output(n);

    for (int k = 0; k < n; k++) {
        real_output[k] = 0.0f;
        imag_output[k] = 0.0f;

        for (int i = 0; i < N; i++) {
            float real_twiddle, imag_twiddle;
            twiddle(&real_twiddle, &imag_twiddle, k * i, n);

            real_output[k] += real_input[i] * real_twiddle - imag_input[i] * imag_twiddle;
            imag_output[k] += real_input[i] * imag_twiddle + imag_input[i] * real_twiddle;
        }
    }

    for (int i = 0; i < n; i++) {
        out_real[i] = real_output[i] / n;
    }
}

// fold操作，将重叠加窗的STFT转换为波形
static void fold(const std::vector<float> & data, int64_t n_out, int64_t n_win, int64_t n_hop, int64_t n_pad, std::vector<float> & output) {
    int64_t output_height = n_out;
    int64_t kernel_w = n_win;
    int64_t stride_w = n_hop;
    int64_t width    = n_out;

    output.resize(width, 0.0f);

    int64_t col_idx = 0;
    for (int64_t w_col = 0; w_col < width; ++w_col) {
        int64_t start = w_col * stride_w - n_pad;
        int64_t end   = start + kernel_w;

        for (int64_t w_im = start; w_im < end; ++w_im) {
            if (w_im >= 0 && w_im < output_height && col_idx < (int64_t) data.size()) {
                output[w_im] += data[col_idx];
            }
            col_idx++;
        }
    }

    output.resize(n_out - 2 * n_pad);
}

// 将嵌入转换为音频
static std::vector<float> embd_to_audio(
        const float * embd,
        const int n_codes,
        const int n_embd,
        const int n_thread) {
    const int n_fft = 1280;
    const int n_hop = 320;
    const int n_win = 1280;
    const int n_pad = (n_win - n_hop)/2;
    const int n_out = (n_codes - 1)*n_hop + n_win;

    std::vector<float> hann(n_fft);

    fill_hann_window(hann.size(), true, hann.data());

    int n_spec = n_embd*n_codes;

    std::vector<float> E (n_spec);
    std::vector<float> S (n_spec);
    std::vector<float> ST(n_spec);

    for (int l = 0; l < n_codes; ++l) {
        for (int k = 0; k < n_embd; ++k) {
            E[k*n_codes + l] = embd[l*n_embd + k];
        }
    }

    for (int k = 0; k < n_embd/2; ++k) {
        for (int l = 0; l < n_codes; ++l) {
            float mag = E[(k           )*n_codes + l];
            float phi = E[(k + n_embd/2)*n_codes + l];

            mag = exp(mag);

            if (mag > 1e2) {
                mag = 1e2;
            }
            S[2*(k*n_codes + l) + 0] = mag*cosf(phi);
            S[2*(k*n_codes + l) + 1] = mag*sinf(phi);
        }
    }

    for (int l = 0; l < n_codes; ++l) {
        for (int k = 0; k < n_embd/2; ++k) {
            ST[l*n_embd + 2*k + 0] = S[2*(k*n_codes + l) + 0];
            ST[l*n_embd + 2*k + 1] = S[2*(k*n_codes + l) + 1];
        }
    }

    std::vector<float> res  (n_codes*n_fft);
    std::vector<float> hann2(n_codes*n_fft);

    std::vector<std::thread> workers(n_thread);
    for (int i = 0; i < n_thread; ++i) {
        workers[i]


// simple_whip_receiver.cpp
// Simplified version that compiles correctly with libdatachannel

#include <rtc/rtc.hpp>
#include <iostream>
#include <thread>
#include <mutex>
#include <queue>
#include <atomic>
#include <chrono>
#include <memory>
#include <cmath>
#include "httplib.h"

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

#ifdef _WIN32
#include <windows.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#endif

// Simple frame structures
struct VideoFrame {
    std::vector<uint8_t> data;  // BGRA format
    uint32_t width;
    uint32_t height;
    uint64_t timestamp;
};

struct AudioFrame {
    std::vector<int16_t> samples;  // PCM 16-bit samples
    uint32_t sampleRate;
    uint32_t channels;
    uint64_t timestamp;
};

class SimpleWHIPReceiver {
private:
    std::shared_ptr<rtc::PeerConnection> peerConnection;
    std::thread workerThread;
    std::atomic<bool> isRunning{false};

    // Frame queues
    std::queue<VideoFrame> videoQueue;
    std::queue<AudioFrame> audioQueue;
    std::mutex videoMutex;
    std::mutex audioMutex;

    std::string endpoint;

    // Statistics
    std::atomic<uint32_t> videoFrameCount{0};
    std::atomic<uint32_t> audioFrameCount{0};

public:
    SimpleWHIPReceiver(const std::string& whipEndpoint) : endpoint(whipEndpoint) {
        rtc::InitLogger(rtc::LogLevel::Verbose); // Reduce log verbosity
        // HTTP server
        httplib::Server svr;

        // WHIP endpoint: /whip
        svr.Post("/whip", [&](const httplib::Request& req, httplib::Response& res) {
            if (req.get_header_value("Content-Type") != "application/sdp") {
                res.status = 415; // Unsupported Media Type
                return;
            }
			std::cout << "Received WHIP POST request" << std::endl;
        });
        svr.listen("localhost", 8080);
    }

    ~SimpleWHIPReceiver() {
        stop();
    }

    bool start() {
        if (isRunning.load()) {
            return false;
        }

        isRunning.store(true);
        workerThread = std::thread(&SimpleWHIPReceiver::run, this);
        return true;
    }

    void stop() {
        if (!isRunning.load()) {
            return;
        }

        isRunning.store(false);

        if (workerThread.joinable()) {
            workerThread.join();
        }

        if (peerConnection) {
            peerConnection->close();
            peerConnection.reset();
        }
    }

    bool getVideoFrame(VideoFrame& frame) {
        std::lock_guard<std::mutex> lock(videoMutex);
        if (videoQueue.empty()) {
            return false;
        }

        frame = std::move(videoQueue.front());
        videoQueue.pop();
        return true;
    }

    bool getAudioFrame(AudioFrame& frame) {
        std::lock_guard<std::mutex> lock(audioMutex);
        if (audioQueue.empty()) {
            return false;
        }

        frame = std::move(audioQueue.front());
        audioQueue.pop();
        return true;
    }

    uint32_t getVideoFrameCount() const { return videoFrameCount.load(); }
    uint32_t getAudioFrameCount() const { return audioFrameCount.load(); }

private:
    void run() {
        try {
            setupConnection();

            // Keep thread alive
            while (isRunning.load()) {
                std::this_thread::sleep_for(std::chrono::milliseconds(100));
            }

        } catch (const std::exception& e) {
            std::cerr << "Worker thread error: " << e.what() << std::endl;
        }
    }

    void setupConnection() {
        // Create configuration
        rtc::Configuration config;
        config.iceServers.emplace_back("stun:stun.l.google.com:19302");

        // Create peer connection
        peerConnection = std::make_shared<rtc::PeerConnection>(config);
        // Create video and audio track descriptions
        auto videoDesc = rtc::Description::Video();
        videoDesc.setDirection(rtc::Description::Direction::SendRecv);
        videoDesc.addH264Codec(102);

        auto audioDesc = rtc::Description::Audio();
        audioDesc.setDirection(rtc::Description::Direction::SendRecv);
        audioDesc.addOpusCodec(111);

        // Add tracks to peer connection
        peerConnection->addTrack(videoDesc);
        peerConnection->addTrack(audioDesc);
        peerConnection->createDataChannel("dummy");
        // Set up state change callback
        peerConnection->onStateChange([this](rtc::PeerConnection::State state) {
            std::cout << "Connection state: " << getStateName(state) << std::endl;
        });

        // Set up track callback
        peerConnection->onTrack([this](std::shared_ptr<rtc::Track> track) {
            handleIncomingTrack(track);
        });

        // Create local description
        peerConnection->onLocalDescription([this](rtc::Description description) {
            std::string sdp = std::string(description)


#include "date.h"

Date::Date()
{
    time_t timestamp = time(NULL);
    struct tm* dateTimeNowPtr = localtime(&timestamp);

    day   = dateTimeNowPtr->tm_mday;
    month = dateTimeNowPtr->tm_mon + 1;
    year  = dateTimeNowPtr->tm_year + 1900;
}
Date::Date(short day , short month , short year)
{
    this->day   = day;
    this->month = month;
    this->year  = year;

    if(!this->isValid())
        throw invalid_argument("Invalid date");
}
Date::Date(const string& dateFormat , const char& delimiter)
{
    string tokenFormat = dateFormat;

    if (tokenFormat.empty())
        throw invalid_argument("Date string is empty");
    this->day = cutNumberBeforeDelimiter(tokenFormat, delimiter);

    if (tokenFormat.empty())
        throw invalid_argument("Month part is missing");
    this->month = cutNumberBeforeDelimiter(tokenFormat, delimiter);

    if (tokenFormat.empty())
        throw invalid_argument("Year part is missing");
    short yearValue = stoi(tokenFormat);
    if (yearValue < 0)
        throw out_of_range("Year cannot be negative");
    this->year = yearValue;

    if(!this->isValid())
       throw invalid_argument("Invalid date format or out of range date");
}
Date::Date(short dayOfYear , short year)
{
    if(dayOfYear <= 0)
        throw out_of_range("Days from beginning of year must be positive");

    short daysInYear = getDaysInYear(year);
    while(dayOfYear > daysInYear)
    {
        dayOfYear -= daysInYear;
        daysInYear = getDaysInYear(++year);
    }
    this->year = year;

    this->month = 1;
    short daysInMonth = getDaysInMonth(this->month , this->year);
    while(dayOfYear > daysInMonth)
    {
        dayOfYear -= daysInMonth;
        increaseByOneMonth(this->month , this->year);
    }

    this->day = dayOfYear;
}

Date Date::convertStringFormatToRecord(const string& dateFormat , const char& delimiter)
{
    Date convertedDate;

    string tokenFormat = dateFormat;

    if (tokenFormat.empty())
        throw invalid_argument("Date string is empty");
    convertedDate.day = cutNumberBeforeDelimiter(tokenFormat, delimiter);

    if (tokenFormat.empty())
        throw invalid_argument("Month part is missing");
    convertedDate.month = cutNumberBeforeDelimiter(tokenFormat, delimiter);

    if (tokenFormat.empty())
        throw invalid_argument("Year part is missing");
    short yearValue = stoi(tokenFormat);
    if (yearValue < 0)
        throw out_of_range("Year cannot be negative");
    convertedDate.year = yearValue;

    if(!convertedDate.isValid())
       throw invalid_argument("Invalid date format or out of range date");
    return convertedDate;
}

short Date::cutNumberBeforeDelimiter(string& str , const char& delimiter)
{
    size_t delimiterPos = str.find(delimiter);

    if(delimiterPos == string::npos)
        throw invalid_argument("Delimiter not found in string");

    string token = str.substr(0, delimiterPos);
    if (token.empty())
        throw invalid_argument("No number before delimiter");

    str.erase(0 , delimiterPos + 1);

    return static_cast<short>(stoi(token));
}

bool Date::isValidDate(const Date& date)
{
    return isValidYear(date.year) && isValidMonth(date.month) && isValidDay(date);
}
bool Date::isValid()
{
    return isValidDate(*this);
}

bool Date::isValidYear(const short& year)
{
    return year > 0;
}
bool Date::isValidYear()
{
    return isValidYear(this->year);
}

bool Date::isValidMonth(const short& month)
{
    return month >= 1 && month <= 12;
}
bool Date::isValidMonth()
{
    return isValidMonth(this->month);
}

bool Date::isValidDay(const Date& date)
{
    return (date.day > 0) && (date.day <= getDaysInMonth(date.month , date.year));
}
bool Date::isValidDay()
{
    return isValidDay(*this);
}
short Date::getDaysInMonth(short month , short year)
{
    if (month < 1 || month > 12)
        return 0;

    short numberOfDaysInMonth[12] = {31, (isLeapYear(year) ? short(29) : short(28)), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    return numberOfDaysInMonth[month - 1];
}
short Date::getDaysInMonth(const Date& date)
{
    return getDaysInMonth(date.month , date.year);
}
short Date::getDaysInCurrentMonth()
{
    return getDaysInMonth(this->month , this->year);
}
bool Date::isLeapYear(short year)
{
    return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}
bool Date::isLeapYear()
{
    return isLeapYear(this->year);
}
Date Date::getCurrentDate()
{
    time_t timestamp = time(NULL);
    struct tm *dateTimeNowPtr = localtime(&timestamp);

    Date currentDate;

    currentDate.day = dateTimeNowPtr->tm_mday;
    currentDate.month = dateTimeNowPtr->tm_mon + 1;
    currentDate.year = dateTimeNowPtr->tm_year + 1900;

    return currentDate;
}
short Date::getDaysInYear(short year) { return isLeapYear(year) ? 366 : 365; }
short


#include <iostream>
#include <array>
#include <random>
#include <locale>
#include <string>

int width = 6, height = 6, max_length = 0;
int matrix[6][6] = {
    {0, 0, 0, 0, 0, 0 },
    {0, 0, 0, 0, 0, 0 },
    {0, 0, 0, 0, 0, 0 },
    {0, 0, 0, 0, 0, 0 },
    {0, 0, 0, 0, 0, 0 },
    {0, 0, 0, 0, 0, 0 },
};

int random1()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dist(0, 5);
    int a = dist(gen);
    return a;
}

int string_length(int number) {
    if (number == 0) return 1;

    number = std::abs(number);
    return static_cast<int>(std::log10(number)) + 1;
}

void print()
{
    std::cout << "_______________" << std::string(max_length * 3, '_') << std::endl;
    for (int i = 0; i < 6; i++)
    {
        std::cout << "| ";
        for (int j = 0; j < 6; j++)
        {
            std::cout << std::string(max_length - string_length(matrix[i][j]), ' ') << matrix[i][j] << " ";
        }
        std::cout << "|" << std::endl;
    }
    std::cout << "_______________" << std::string(max_length * 3, '_') << std::endl;
}

void mixing(int vector)
{
    int i_,j_;
    switch (vector) {
    case 1:
        for (int a = 0; a < 6; a++)
        {
            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j < 6; j++)
                {
                    i_ = i + 1;
                    if (matrix[i_][j] == matrix[i][j]) {
                        matrix[i_][j] = matrix[i_][j] + matrix[i][j];
                        matrix[i][j] = 0;
                    }
                    if (matrix[i_][j] == 0) {

                        matrix[i_][j] = matrix[i_][j] + matrix[i][j];
                        matrix[i][j] = 0;
                    }
                }
            }
        }
        break;
    case 2:
        for (int a = 0; a < 6; a++)
        {
            for (int i = 5; i > 0; i--)
            {
                for (int j = 0; j < 6; j++)
                {
                    i_ = i - 1;
                    if (matrix[i_][j] == matrix[i][j]) {
                        matrix[i_][j] = matrix[i_][j] + matrix[i][j];
                        matrix[i][j] = 0;
                    }
                    if (matrix[i_][j] == 0) {

                        matrix[i_][j] = matrix[i_][j] + matrix[i][j];
                        matrix[i][j] = 0;
                    }
                }
            }
        }
        break;
    case 3:
        for (int a = 0; a < 6; a++)
        {
            for (int i = 0; i < 6; i++)
            {
                for (int j = 0; j < 5; j++)
                {
                    j_ = j + 1;
                    if (matrix[i][j_] == matrix[i][j]) {
                        matrix[i][j_] = matrix[i][j_] + matrix[i][j];
                        matrix[i][j] = 0;
                    }
                    if (matrix[i][j_] == 0) {

                        matrix[i][j_] = matrix[i][j_] + matrix[i][j];
                        matrix[i][j] = 0;
                    }
                }
            }
        }
        break;
    case 4:
        for (int a = 0; a < 6; a++)
        {
            for (int i = 0; i < 6; i++)
            {
                for (int j = 5; j > 0; j--)
                {
                    j_ = j - 1;
                    if (matrix[i][j_] == matrix[i][j]) {
                        matrix[i][j_] = matrix[i][j_] + matrix[i][j];
                        matrix[i][j] = 0;
                    }
                    if (matrix[i][j_] == 0) {

                        matrix[i][j_] = matrix[i][j_] + matrix[i][j];
                        matrix[i][j] = 0;
                    }
                }
            }
        }
        break;
    }
}

void check() {
    int count = 0, max = 0;
    for (int i = 0; i < 6; i++) {
        for (int j = 0; j < 6; j++) {
            if (matrix[i][j] == 0) { count++; }
            if (max < matrix[i][j]) { max = matrix[i][j]; }
        }
    }
    if (count == 0) {
        std::cout << "Конец игры, твой результат: " << max;
    }
    max_length = string_length(max);
}

void spawn(int n) {
    int a1, a2;
    for (int i = 0; i < n;)
    {
        a1 = random1(), a2 = random1();
        if (matrix[a1][a2] != 0)
        {
            a1 = random1(), a2 = random1();
            continue;
        }
        else
        {
            matrix[a1][a2] = 2;
            i++;
            check();
        }
    }
}

int main()
{
    int n, m;
    std::locale::global(std::locale("")); // исправляет проблемы с показом руского языка
    std::cout << "Сколько 2 спавнить за раунд: ";
    std::cin >> n;
    spawn(n);
    print();
    int end = 5;
    while (end != 0)
    {
        std::cout << "0 - конец игры, 1 - вниз, 2 - вверх, 3 - право, 4 - лево" << std::endl;
        std::cin >> m;
        mixing(m);
        spawn(n);
        print();
    }
}


#include <iostream>
using namespace std;

class Student{
        private:
                string name;
                int rollno;
                string degree;
                string hostel;
                float currentCGPA;

        void updatedetails(string n, int r, string d, string h, float cgpa){
                name = n;
                rollno = r;
                degree = d;
                hostel = h;
                currentCGPA = cgpa;
        }

        void updateHostel(string h) {
        hostel = h;
        }
public:
        void changedetails(string n, int r, string d, string h, float cgpa) {
                updatedetails(n, r, d, h, cgpa);
        }

        void updateCGPA(float cgpa) {
                currentCGPA = cgpa;
        }

        void displayDetails() {
                cout << "\n--- Student Details ---\n";
                cout << "Name: " << name << endl;
                cout << "Roll No: " << rollno << endl;
                cout << "Degree: " << degree << endl;
                cout << "Hostel: " << hostel << endl;
                cout << "Current CGPA: " << currentCGPA << endl;
        }
        void changehostel(string h){
                updateHostel(h);
        };
        void adddetails(float cgpa){
                updateCGPA(cgpa);
        };
};

int main(){
        Student s;
        s.changedetails("Raman", 101, "B.Tech", "Hostel-A", 8.5);
        s.displayDetails();
        s.updateCGPA(9.1);
        cout << "\nAfter updating CGPA:";
        s.displayDetails();
        s.changehostel("Hostel-B");
        cout << "\nAfter updating Hostel:";
        s.displayDetails();
        return 0;
}


#include <windows.h>
#include <commctrl.h>
#include <shellapi.h>
#include <string>
#include <vector>
#include <sstream>
#include <iomanip>
#include <thread>
#include <mutex>
#include <atomic>
#include <gdiplus.h>
#include <fstream>
#include <ctime>
#include <algorithm>
#include <locale>
#include <shlobj.h>
#include <objbase.h>
#include <shlguid.h>

// 定义Unicode宏
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif

using namespace Gdiplus;

// 控件ID
#define ID_BUTTON_ADD       1001
#define ID_BUTTON_CLEAR     1002
#define ID_SCROLL           1003
#define ID_EDIT_TASK        1004
#define ID_EDIT_DESC        1005
#define ID_BUTTON_SAVE      1006
#define ID_BUTTON_CANCEL    1007
#define ID_CHECK_AUTOSTART  1008

// 托盘图标相关
#define WM_TRAYICON         (WM_USER + 1)
#define ID_TRAY_SHOW        2001
#define ID_TRAY_EXIT        2002

// 全局变量
HWND g_hWnd = NULL;
HWND g_hBtnAdd = NULL;
HWND g_hBtnSave = NULL;
HWND g_hBtnCancel = NULL;
HWND g_hEditTask = NULL;
HWND g_hEditDesc = NULL;
HWND g_hScrollWnd = NULL;
HWND g_hCheckAutoStart = NULL;
std::string g_statusText = "欢迎使用待办清单管理工具";
std::mutex g_dataMutex;
NOTIFYICONDATAW g_trayIcon = {0};
bool g_isTrayIconAdded = false;

// 编辑状态
bool g_isEditing = false;
int g_editingTaskId = -1;

// 滚动相关 - 分别为待完成和已完成区域
int g_pendingScrollPos = 0;
int g_completedScrollPos = 0;
int g_maxPendingScrollPos = 0;
int g_maxCompletedScrollPos = 0;
int g_currentScrollArea = 0; // 0=待完成区域, 1=已完成区域

// 窗口吸附相关
bool g_isSnapped = false;           // 是否已吸附
bool g_isHidden = false;            // 是否已隐藏
int g_snapSide = 0;                 // 吸附边：0=无, 1=左, 2=右, 3=上, 4=下
RECT g_normalRect = {0};            // 正常状态下的窗口位置
RECT g_hiddenRect = {0};            // 隐藏状态下的窗口位置
const int SNAP_DISTANCE = 30;      // 吸附距离，增加灵敏度
const int HIDE_WIDTH = 10;          // 隐藏时露出的宽度
UINT_PTR g_hideTimer = 0;           // 隐藏定时器
const int HIDE_DELAY = 1000;        // 隐藏延迟（毫秒）
HHOOK g_mouseHook = NULL;           // 全局鼠标钩子

// 任务状态
enum TaskStatus {
    TASK_PENDING,       // 待完成
    TASK_IN_PROGRESS,   // 进行中
    TASK_COMPLETED,     // 已完成
    TASK_CANCELLED      // 已取消
};

// 任务优先级
enum TaskPriority {
    PRIORITY_LOW,       // 低优先级
    PRIORITY_NORMAL,    // 普通优先级
    PRIORITY_HIGH,      // 高优先级
    PRIORITY_URGENT     // 紧急
};

// 任务项结构
struct TaskItem {
    int id;                         // 任务ID
    std::string title;              // 任务标题
    std::string description;        // 任务描述
    TaskStatus status;              // 任务状态
    TaskPriority priority;          // 优先级
    std::string createTime;         // 创建时间
    std::string completeTime;       // 完成时间

    TaskItem() : id(0), status(TASK_PENDING), priority(PRIORITY_NORMAL) {
        // 获取当前时间作为创建时间
        time_t now = time(0);
        char timeStr[100];
        struct tm timeinfo;
        localtime_s(&timeinfo, &now);
        strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &timeinfo);
        createTime = timeStr;
    }
};

// 待办清单管理器
struct TodoManager {
    std::vector<TaskItem> tasks;
    int nextId = 1;

    int addTask(const std::string& title, const std::string& desc = "", TaskPriority priority = PRIORITY_NORMAL) {
        TaskItem task;
        task.id = nextId++;
        task.title = title;
        task.description = desc;
        task.priority = priority;
        tasks.push_back(task);
        return task.id;
    }

    bool removeTask(int id) {
        auto it = std::find_if(tasks.begin(), tasks.end(), [id](const TaskItem& task) {
            return task.id == id;
        });
        if (it != tasks.end()) {
            tasks.erase(it);
            return true;
        }
        return false;
    }

    bool updateTaskStatus(int id, TaskStatus status) {
        auto it = std::find_if(tasks.begin(), tasks.end(), [id](TaskItem& task) {
            return task.id == id;
        });
        if (it != tasks.end()) {
            it->status = status;
            if (status == TASK_COMPLETED) {
                time_t now = time(0);
                char timeStr[100];
                struct tm timeinfo;
                localtime_s(&timeinfo, &now);
                strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &timeinfo);
                it->completeTime = timeStr;
            }
            return true;
        }
        return false;
    }

    std::vector<TaskItem> getTasksByStatus(TaskStatus status) {
        std::vector<TaskItem> result;
        for (const auto& task : tasks) {
            if (task.status == status) {
                result.push_back(task);
            }
        }
        return result;
    }
};

TodoManager g_todoManager;

// 函数声明
void DrawRoundedRect(Graphics& graphics, Brush& brush, Pen& pen, int x, int y, int width, int height, int radius);
std::wstring StringToWString(const std::string& str);
std::string WStringToString(const std::wstring& wstr);
std::wstring ConfigStringToWString(const std::string& str);
std::string EscapeJsonString(const std::string& str);
std::string UnescapeJsonString(const std


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

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

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

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

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

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

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

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

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

  ::CoUninitialize();
  return EXIT_SUCCESS;
}


#include "DvsRgbFusionCamera/dvs/DvsEventCamera.hpp"
#include "DvsenseBase/logging/logger.hh"

namespace dvsense
{

    DvsEventCamera::DvsEventCamera()
    {
    }

    DvsEventCamera::~DvsEventCamera()
    {
        if (trigger_thread_.joinable()) trigger_thread_.join();
    }

    bool DvsEventCamera::findCamera(std::vector<dvsense::CameraDescription>& cameraDescs)
    {
        cameraDescs = camera_manager_.getCameraDescs();

        if (cameraDescs.empty()) {
            std::cout << "No available dvsCamera" << std::endl;
            return false;
        }

        std::cout << cameraDescs.size() << " dvs camera(s) found" << std::endl;
        std::cout << "Serial Number: " << cameraDescs.front().serial << std::endl;

        return true;
    }

    bool DvsEventCamera::isConnect()
    {
        return dvs_camera_->isConnected();
    }

    bool DvsEventCamera::openCamera(dvsense::CameraDescription cameraDesc)
    {
        camera_desc_ = cameraDesc;
        dvs_camera_ = camera_manager_.openCamera(cameraDesc.serial);
        openDvsTriggerIn();
        std::shared_ptr<dvsense::CameraTool> trigger_in = dvs_camera_->getTool(dvsense::ToolType::TOOL_TRIGGER_IN);
        bool ret = trigger_in->setParam("enable", true);
        if (!ret) {
            return false;
        }
        //std::shared_ptr<dvsense::CameraTool> erc_tool = dvs_camera_->getTool(dvsense::ToolType::TOOL_EVENT_RATE_CONTROL);
        //ret = erc_tool->setParam("enable", true);
        //ret = erc_tool->setParam("max_event_rate", 30);
        //if (!ret) {
        //    return false;
        //}

        std::shared_ptr<dvsense::CameraTool> bias_tool = dvs_camera_->getTool(dvsense::ToolType::TOOL_BIAS);
        ret = bias_tool->setParam("bias_diff_on", 18);
        ret = bias_tool->setParam("bias_diff_off", 26);
        if (!ret) {
            return false;
        }
        return true;
    }

    int DvsEventCamera::startCamera()
    {
        if (!dvs_camera_running_)
        {
            dvs_camera_->start();
            dvs_camera_running_ = true;
        }
        return 0;
    }

    void DvsEventCamera::stopCamera()
    {
        dvs_camera_->stop();
        dvs_camera_running_ = false;
    }

    uint32_t DvsEventCamera::registerEventCallback(const dvsense::EventsStreamHandleCallback& callback) {
        return dvs_camera_->addEventsStreamHandleCallback(callback);
    }

    bool DvsEventCamera::removeEventCallback(uint32_t callback_id)
    {
        return dvs_camera_->removeEventsStreamHandleCallback(callback_id);
    }

    void DvsEventCamera::startRecording(std::string output_dir)
    {
        dvs_camera_->startRecording(output_dir);
    }

    void DvsEventCamera::stopRecording()
    {
        dvs_camera_->stopRecording();
    }

    uint16_t DvsEventCamera::getDvsWidth()
    {
        return dvs_camera_->getWidth();
    }

    uint16_t DvsEventCamera::getDvsHeight()
    {
        return dvs_camera_->getHeight();
    }

    uint32_t DvsEventCamera::addTriggerInCallback(NewTriggerInCallback newTriggerInCallback)
    {
        trigger_in_callback_id_num_++;
        new_trigger_in_callbacks_.insert(
            { trigger_in_callback_id_num_, newTriggerInCallback }
        );
        return trigger_in_callback_id_num_;
    }

    bool DvsEventCamera::removeTriggerInCallback(uint32_t callback_id)
    {
        auto it = new_trigger_in_callbacks_.find(callback_id);
        if (it != new_trigger_in_callbacks_.end()) {
            new_trigger_in_callbacks_.erase(it);
            return true;
        }
        return false;
    }

    void DvsEventCamera::openDvsTriggerIn()
    {
        dvs_camera_->addTriggerInCallback(
            [this](const dvsense::EventTriggerIn begin) {
                for (auto trigger : new_trigger_in_callbacks_)
                {
                    trigger.second(begin);
                }
            }
        );

    }

    std::shared_ptr<dvsense::CameraTool> DvsEventCamera::getTool(dvsense::ToolType type)
    {
        return dvs_camera_->getTool(type);
    }

}


#include "display.h"
#include "logging.h"
#include "declarations.h"

// This function will be called from the main setup()
void setupDisplay() {
    strip.begin();
    strip.setBrightness(displayBrightness);
    strip.show(); // Initialize all pixels to 'off'
}

void createArray8x8() {
    for (int i = 0; i < MATRIX_HEIGHT; i++) {
        for (int j = 0; j < MATRIX_WIDTH; j++) {
            displayArray[i][j] = BLACK;
        }
    }
}

void getNextBorderPoint() {
    const int SIZE = 8;
    const int BORDER_POINTS = (SIZE * 4) - 4;
    int i = highlightIndex;

    if (i < SIZE) {
        highlightX = i;
        highlightY = 0;
    } else if (i < SIZE + SIZE - 1) {
        highlightX = SIZE - 1;
        highlightY = i - (SIZE - 1);
    } else if (i < SIZE + SIZE - 1 + SIZE - 1) {
        highlightX = (SIZE - 1) - (i - (2 * SIZE - 2));
        highlightY = SIZE - 1;
    } else {
        highlightX = 0;
        highlightY = (SIZE - 1) - (i - (3 * SIZE - 3));
    }

    highlightIndex = (highlightIndex + 1) % BORDER_POINTS;
}

void updateItem(int row, int col, Color color) {
    if (row >= 0 && row < MATRIX_HEIGHT && col >= 0 && col < MATRIX_WIDTH) {
        displayArray[row][col] = color;
    }
}

void drawBorder() {
    updateItem(0, 1, CYAN);
    updateItem(0, 2, CYAN);
    updateItem(7, 1, CYAN);
    updateItem(7, 2, CYAN);
    updateItem(0, 5, MAGENTA);
    updateItem(0, 6, MAGENTA);
    updateItem(7, 5, MAGENTA);
    updateItem(7, 6, MAGENTA);

    for (int i = 0; i < 8; i++) {
        updateItem(i, 0, CYAN);
        updateItem(i, 3, CYAN);
        updateItem(i, 4, MAGENTA);
        updateItem(i, 7, MAGENTA);
    }
}

void state_unknown(int bike, int row) {
    int colStart = (bike == 1) ? 0 : 4;
    int rowStart = (row % 2 == 0) ? 2 : 3;
    updateItem(rowStart, colStart + 1, RED);
    updateItem(rowStart, colStart + 2, RED);

    updateItem(rowStart + 2, colStart + 1, RED);
    updateItem(rowStart + 2, colStart + 2, RED);
}

void state_charging(int bike, int row) {
    int colStart = (bike == 1) ? 0 : 4;
    updateItem(row, colStart + 1, BLUE);
    updateItem(row, colStart + 2, BLUE);
}

void state_disconnected(int bike, int row) {
    int colStart = (bike == 1) ? 0 : 4;
    for (int i = 1; i < 7; i++) {
        int col = ((i + row) % 2 == 0) ? 1 : 2;
        updateItem(i, colStart + col, YELLOW);
    }
}

void noWifi(int row) {
    Color pixelColor = (row % 2 == 0) ? BLUE : RED;
    updateItem(0, 0, pixelColor);

    for (int r = 1; r < 8; r += 2) {
        for (int c = r; c < 8; c++) {
            updateItem(c, (7 - r), RED);
        }
    }
}

void noHass(int row) {
    Color pixelColor = (row % 2 == 0) ? GREEN : YELLOW;
    updateItem(0, 0, pixelColor);

    for (int r = 1; r < 8; r += 2) {
        for (int c = r; c < 8; c++) {
            updateItem(c, (7 - r), BLUE);
        }
    }
}

void otaInProgress() {
    for (int y = 0; y < 8; y++) {
        for (int x = 0; x < 8; x++) {
            if ((x + y) % 2 == 0) {
                updateItem(x, y, YELLOW);
            }
        }
    }
}

int getPixelIndex(int row, int col) {
    // Simplified from serpentine layout to standard left-to-right wiring to fix pixel scrambling.
    return (row * MATRIX_WIDTH) + col;
}

uint8_t highlightBrightness(uint8_t tone) {
    // Add a fixed value to each color component to make it visibly brighter.
    const uint8_t brightness_increase = 50;
    //uint16_t new_tone = tone + brightness_increase;
    uint16_t new_tone = tone - brightness_increase;
    if (new_tone > 255) {
        new_tone = 255;
    }
    if (new_tone < 0) {
        new_tone = 0;
    }
    return (uint8_t)new_tone;
}

uint32_t highlightPixel(int row, int col, uint32_t rgbColor) {
    if (row == highlightY && col == highlightX) {
        // Unpack the 32-bit color into R, G, B components
        uint8_t r = (rgbColor >> 16) & 0xFF;
        uint8_t g = (rgbColor >> 8) & 0xFF;
        uint8_t b =  rgbColor & 0xFF;

        // Change brightness of each component for highlight effect
        r = highlightBrightness(r);
        g = highlightBrightness(g);
        b = highlightBrightness(b);

        // Repack the components into a 32-bit color
        return strip.Color(r, g, b);
    }
    return rgbColor;
}

uint32_t translateColor(Color colorValue) {
    switch (colorValue) {
        case BLACK:   return strip.Color(0, 0, 0);
        case WHITE:   return strip.Color(255, 255, 255);
        case RED:     return strip.Color(255, 0, 0);
        case GREEN:   return strip.Color(0, 255, 0);
        case BLUE:    return strip.Color(0, 0, 255);
        case YELLOW:  return strip.Color(255, 255, 0);
        case CYAN:    return strip.Color(0, 255, 255);
        case MAGENTA: return strip.Color(255, 0, 255);
        default:     return strip.Color(0, 0, 0);
    }
}

void drawMatrix() {
    for (int i = 0; i < MATRIX_HEIGHT; i++) {
        for (int j = 0; j < MATRIX_WIDTH; j++) {
            int pixelIndex = getPixelIndex(i, j);
            Color colo


#include <iostream>
#include <queue>
#include <string>
#include <fstream>
#include <ctime>
using namespace std;

struct Patient {
    string name;
    int age;
    int priority;
    string timestamp;

    bool operator<(const Patient& other) const {
        return priority < other.priority;  // max heap
    }
};

priority_queue<Patient> pq;

string getCurrentTimestamp() {
    time_t now = time(0);
    tm* ltm = localtime(&now);
    char buf[20];
    snprintf(buf, sizeof(buf), "%02d-%02d-%04d %02d:%02d:%02d",
         ltm->tm_mday, ltm->tm_mon + 1, 1900 + ltm->tm_year,
         ltm->tm_hour, ltm->tm_min, ltm->tm_sec);
    return string(buf);
}

void exportToCSV() {
    ofstream file("appointments.csv");
    file << "Name,Age,Priority,Timestamp\n";
    priority_queue<Patient> temp = pq;
    while (!temp.empty()) {
        Patient p = temp.top();
        temp.pop();
        file << p.name << "," << p.age << "," << p.priority << "," << p.timestamp << "\n";
    }
    file.close();
    cout << "Appointments exported to appointments.csv\n";
}

void bookSlot() {
    string name;
    int age, priority;
    cout << "\n--- Book a Slot ---\n";
    cout << "Enter name: ";
    cin >> name;
    cout << "Enter age: ";
    cin >> age;
    cout << "Enter priority (1-10): ";
    cin >> priority;
    string time = getCurrentTimestamp();

    Patient p;
    p.name = name;
    p.age = age;
    p.priority = priority;
    p.timestamp = time;

    pq.push(p);
    cout << "Slot booked at: " << time << "\n";
}

void viewSchedule() {
    priority_queue<Patient> temp = pq;
    cout << "\n--- Scheduled Patients (High to Low Priority) ---\n";
    int slot = 1;
    while (!temp.empty()) {
        Patient p = temp.top();
        temp.pop();
        cout << "Slot " << slot++ << ": " << p.name << " | Age: " << p.age
             << " | Priority: " << p.priority << " | Time: " << p.timestamp << "\n";
    }
}

int main() {
    int choice;
    while (true) {
        cout << "\n--- Covid Test Center Scheduler ---\n";
        cout << "1. Book a Slot\n2. View Schedule\n3. Export to CSV\n4. Exit\nEnter choice: ";
        cin >> choice;
        switch (choice) {
            case 1: bookSlot(); break;
            case 2: viewSchedule(); break;
            case 3: exportToCSV(); break;
            case 4: cout << "Exiting..."; return 0;
            default: cout << "Invalid option\n";
        }
    }
}


#include "util.h"
#include <regex>
#include <cmath>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

using std::ceil;
using std::floor;

using namespace std;

namespace tyme::util {
    const double ShouXingUtil::PI_2 = 2 * M_PI;

    const double ShouXingUtil::ONE_THIRD = 1.0 / 3;

    const int ShouXingUtil::SECOND_PER_DAY = 86400;

    const double ShouXingUtil::SECOND_PER_RAD = 180 * 3600 / M_PI;

    const double ShouXingUtil::NUT_B[] = {
        2.1824, -33.75705, 36e-6, -1720, 920,
        3.5069, 1256.66393, 11e-6, -132, 57,
        1.3375, 16799.4182, -51e-6, -23, 10,
        4.3649, -67.5141, 72e-6, 21, -9,
        0.04, -628.302, 0, -14, 0,
        2.36, 8328.691, 0, 7, 0,
        3.46, 1884.966, 0, -5, 2,
        5.44, 16833.175, 0, -4, 2,
        3.69, 25128.110, 0, -3, 0,
        3.55, 628.362, 0, 2, 0
    };

    const double ShouXingUtil::DT_AT[] = {
        -4000, 108371.7, -13036.80, 392.000, 0.0000,
        -500, 17201.0, -627.82, 16.170, -0.3413,
        -150, 12200.6, -346.41, 5.403, -0.1593,
        150, 9113.8, -328.13, -1.647, 0.0377,
        500, 5707.5, -391.41, 0.915, 0.3145,
        900, 2203.4, -283.45, 13.034, -0.1778,
        1300, 490.1, -57.35, 2.085, -0.0072,
        1600, 120.0, -9.81, -1.532, 0.1403,
        1700, 10.2, -0.91, 0.510, -0.0370,
        1800, 13.4, -0.72, 0.202, -0.0193,
        1830, 7.8, -1.81, 0.416, -0.0247,
        1860, 8.3, -0.13, -0.406, 0.0292,
        1880, -5.4, 0.32, -0.183, 0.0173,
        1900, -2.3, 2.06, 0.169, -0.0135,
        1920, 21.2, 1.69, -0.304, 0.0167,
        1940, 24.2, 1.22, -0.064, 0.0031,
        1960, 33.2, 0.51, 0.231, -0.0109,
        1980, 51.0, 1.29, -0.026, 0.0032,
        2000, 63.87, 0.1, 0, 0,
        2005, 64.7, 0.21, 0, 0,
        2012, 66.8, 0.22, 0, 0,
        // 2018, 69.0, 0.36, 0, 0,
        // 使用skyfeild的DE440s△T预测数据拟合
        2016, 68.1024, 0.5456, -0.0542, -0.001172,
        2020, 69.3612, 0.0422, -0.0502, 0.006216,
        2024, 69.1752, -0.0335, -0.0048, 0.000811,
        2028, 69.0206, -0.0275, 0.0055, -0.000014,
        2032, 68.9981, 0.0163, 0.0054, 0.000006,
        2036, 69.1498, 0.0599, 0.0053, 0.000026,
        2040, 69.4751, 0.1035, 0.0051, 0.000046,
        2044, 69.9737, 0.1469, 0.0050, 0.000066,
        2048, 70.6451, 0.1903, 0.0049, 0.000085,
        2050, 71.0457
    };

    const double ShouXingUtil::XL0[] = {
        10000000000.0,
        20, 578, 920, 1100, 1124, 1136, 1148, 1217, 1226, 1229, 1229, 1229, 1229, 1937, 2363, 2618, 2633, 2660, 2666,
        17534704567.0, 0.00000000000, 0.00000000000, 334165646, 4.669256804, 6283.075849991, 3489428, 4.6261024,
        12566.1517000, 349706, 2.744118, 5753.384885, 341757, 2.828866, 3.523118, 313590, 3.627670, 77713.771468,
        267622, 4.418084, 7860.419392, 234269, 6.135162, 3930.209696, 132429, 0.742464, 11506.769770, 127317, 2.037097,
        529.690965, 119917, 1.109629, 1577.343542, 99025, 5.23268, 5884.92685, 90186, 2.04505, 26.29832, 85722, 3.50849,
        398.14900, 77979, 1.17883, 5223.69392, 75314, 2.53339, 5507.55324, 50526, 4.58293, 18849.22755, 49238, 4.20507,
        775.52261, 35666, 2.91954, 0.06731, 31709, 5.84902, 11790.62909, 28413, 1.89869, 796.29801, 27104, 0.31489,
        10977.07880, 24281, 0.34481, 5486.77784, 20616, 4.80647, 2544.31442, 20539, 1.86948, 5573.14280, 20226, 2.45768,
        6069.77675, 15552, 0.83306, 213.29910, 13221, 3.41118, 2942.46342, 12618, 1.08303, 20.77540, 11513, 0.64545,
        0.98032, 10285, 0.63600, 4694.00295, 10190, 0.97569, 15720.83878, 10172, 4.26680, 7.11355, 9921, 6.2099,
        2146.1654, 9761, 0.6810, 155.4204, 8580, 5.9832, 161000.6857, 8513, 1.2987, 6275.9623, 8471, 3.6708, 71430.6956,
        7964, 1.8079, 17260.1547, 7876, 3.0370, 12036.4607, 7465, 1.7551, 5088.6288, 7387, 3.5032, 3154.6871, 7355,
        4.6793, 801.8209, 6963, 0.8330, 9437.7629, 6245, 3.9776, 8827.3903, 6115, 1.8184, 7084.8968, 5696, 2.7843,
        6286.5990, 5612, 4.3869, 14143.4952, 5558, 3.4701, 6279.5527, 5199, 0.1891, 12139.5535, 5161, 1.3328, 1748.0164,
        5115, 0.2831, 5856.4777, 4900, 0.4874, 1194.4470, 4104, 5.3682, 8429.2413, 4094, 2.3985, 19651.0485, 3920,
        6.1683, 10447.3878, 3677, 6.0413, 10213.2855, 3660, 2.5696, 1059.3819, 3595, 1.7088, 2352.8662, 3557, 1.7760,
        6812.7668, 3329, 0.5931, 17789.8456, 3041, 0.4429, 83996.8473, 3005, 2.7398, 1349.8674, 2535, 3.1647, 4690.4798,
        2474, 0.2148, 3.5904, 2366, 0.4847, 8031.0923, 2357, 2.0653, 3340.6124, 2282, 5.2220, 4705.7323, 2189, 5.5559,
        553.5694, 2142, 1.4256, 16730.4637, 2109, 4.1483, 951.7184, 2030, 0.3713, 283.8593, 1992, 5.2221, 12168.0027,
        1986, 5.7747, 6309.3742, 1912, 3.8222, 23581.2582, 1889, 5.3863, 149854.4001, 1790, 2.2149, 13367.9726, 1748,
        4.5605, 135.0651, 1622, 5.9884, 11769.8537, 1508, 4.1957, 6256.7775, 1442, 4.1932, 242.7286, 1435, 3.7236,
        38.0277, 1397, 4.4014, 6681.2249, 1362, 1.8893, 7632.9433, 1250, 1.1305, 5.5229, 1205, 2.6223, 955.5997, 1200,
        1.0035


#include<iostream>
#include<raylib.h>
using namespace std;

int PlayerScore = 0;
int CpuScore = 0;

//Colors
Color Green = Color{ 38,185,154,255 };
Color Dark_Green = Color{ 20,160,133,255 };
Color Light_Green = Color{ 129,204,184,255 };
Color Yellow = Color{ 243,213,91,255 };

class Ball
{
public:
	float x, y;
	int speed_x,speed_y;
	int radius;
	void Draw()
	{
		DrawCircle(x, y, radius,Yellow);
	}

	void RsetBall()
	{
		x = GetScreenWidth() / 2;
		y = GetScreenHeight() / 2;

		int SpeedChoices[2] = { -1,1 };
		speed_x *= SpeedChoices[GetRandomValue(1, 0)];
		speed_y *= SpeedChoices[GetRandomValue(1, 0)];
	}

	void update()
	{
		x += speed_x;
		y += speed_y;

		if (x + radius >= GetScreenWidth())
		{
			CpuScore++;
			RsetBall();

		}
		if(x-radius<=0)
		{
				PlayerScore++;
				RsetBall();
		}

		if (y + radius >= GetScreenHeight() || y - radius <= 0)
		{
			speed_y *= -1;
		}
	}

};

class Player
{
protected:
	void Movement_Limits()
	{
		if (y+height >=GetScreenHeight())
		{
			y = GetScreenHeight()-height;
		}

		if (y <= 0)
		{
			y = 0;
		}
	}

	public:
	float x, y, width, height;
	int speed;

	void draw()
	{
		DrawRectangleRounded(Rectangle{ x,y,width,height }, 0.7, 0, WHITE);

	}

	void Update()
	{
		if (IsKeyDown(KEY_UP))
		{
			y -= speed;
		}
		if (IsKeyDown(KEY_DOWN))
		{
			y += speed;
		}

		Movement_Limits();
	}

};

class CPU  : public Player
{
public:
	void Update(int ball_y) {
		if (y+height/2 < ball_y)
		{
			y =	y+speed;
		}
		if (y + height / 2 > ball_y)
		{
			y -= speed;
		}

	}

};

Ball ball;
Player player;
CPU cpu;

int main()
{
	cout << "Starting the Game ...";
	const int Screen_width = 1280;
	const int Screen_height = 720;
	InitWindow(Screen_width,Screen_height,"Ping Pong Game!");
	SetTargetFPS(60);

	//Ball Info
	ball.x = Screen_width / 2;
	ball.y = Screen_height / 2;
	ball.radius = 20;
	ball.speed_x = 7;
	ball.speed_y = 7;

	//Player Info
	player.height = 120;
	player.width = 25;
	player.x = Screen_width - 35;
	player.y = Screen_height / 2 - 60;
	player.speed = 10;

	//Cpu Info
	cpu.height = 120;
	cpu.width = 25;
	cpu.x = 10;
	cpu.y = Screen_height / 2 - 60;
	cpu.speed = 7;

	while (WindowShouldClose() == false)
	{
		BeginDrawing();

		//Colors
		ClearBackground(Green);
		DrawRectangle(Screen_width / 2, 0, Screen_width / 2, Screen_height, Dark_Green);
		DrawCircle(Screen_width / 2, Screen_height / 2, 150, Light_Green);

		//Collisions
		if (CheckCollisionCircleRec(Vector2{ ball.x,ball.y }, ball.radius, Rectangle{ player.x,player.y,player.width,player.height }))
		{
			ball.speed_x *= -1;
		}
		if (CheckCollisionCircleRec(Vector2{ ball.x,ball.y }, ball.radius, Rectangle{ cpu.x,cpu.y,cpu.width,cpu.height }))
		{
			ball.speed_x *= -1;
		}

		//Updates
		ball.update();
		player.Update();
		cpu.Update(ball.y);

		//Draw
		DrawLine(Screen_width / 2, 0, Screen_width / 2, Screen_height, WHITE);
		ball.Draw();
		player.draw();
		cpu.draw();

		//Scores
		DrawText(TextFormat("%i", CpuScore), Screen_width / 4, 40, 80, WHITE);
		DrawText(TextFormat("%i", PlayerScore), 3 * Screen_width / 4, 40, 80, WHITE);

		EndDrawing();
	}

	CloseWindow();
	return 0;
}


/*
 *  IXSocketFactory.cpp
 *  Author: Benjamin Sergeant
 *  Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
 */

#include "IXSocketFactory.h"

#include "IXUniquePtr.h"
#ifdef IXWEBSOCKET_USE_TLS

#ifdef IXWEBSOCKET_USE_MBED_TLS
#include "IXSocketMbedTLS.h"
#elif defined(IXWEBSOCKET_USE_OPEN_SSL)
#include "IXSocketOpenSSL.h"
#elif __APPLE__
#include "IXSocketAppleSSL.h"
#endif

#else

#include "IXSocket.h"

#endif

namespace ix
{
    std::unique_ptr<Socket> createSocket(bool tls,
                                         int fd,
                                         std::string& errorMsg,
                                         const SocketTLSOptions& tlsOptions)
    {
        (void) tlsOptions;
        errorMsg.clear();
        std::unique_ptr<Socket> socket;

        if (!tls)
        {
            socket = ix::make_unique<Socket>(fd);
        }
        else
        {
#ifdef IXWEBSOCKET_USE_TLS
#if defined(IXWEBSOCKET_USE_MBED_TLS)
            socket = ix::make_unique<SocketMbedTLS>(tlsOptions, fd);
#elif defined(IXWEBSOCKET_USE_OPEN_SSL)
            socket = ix::make_unique<SocketOpenSSL>(tlsOptions, fd);
#elif defined(__APPLE__)
            socket = ix::make_unique<SocketAppleSSL>(tlsOptions, fd);
#endif
#else
            errorMsg = "TLS support is not enabled on this platform.";
            return nullptr;
#endif
        }

        if (!socket->init(errorMsg))
        {
            socket.reset();
        }

        return socket;
    }
} // namespace ix


#include <cstdio>
#include <queue>
#include <vector>

struct TNode
{
    int data;
    TNode*lchild;
    TNode*rchild;
};

void push_left(TNode*&root,int val)
{
    TNode*node = new TNode;
    node->data = val;
    node->lchild = NULL;
    node->rchild = NULL;

    if (!root)
    {
        root = node;
    }

    if (root->lchild == NULL)
    {
        push_left(root->lchild,val);
    }
    else if (root->rchild == NULL)
    {
        push_left(root->rchild,val);
    }
    else
    {
        TNode*temp = root->lchild;
        push_left(temp,val);
    }
    // 不JB玩了

}

TNode* add_left(TNode*&parent,int val)
{
    TNode*node = new TNode;
    node->data = val;
    node->lchild = nullptr;
    node->rchild = nullptr;

    if (!parent)
    {
        parent = node;
        return node;
    }

    if (parent->lchild == NULL)
    {
        parent->lchild = node;
        return node;
    }
    else if (parent->rchild == NULL)
    {
        parent ->rchild = node;
        return node;
    }
    else
    {
        return parent;
    }
}

TNode* add_right(TNode*&parent,int val)
{
    TNode*node = new TNode;
    node->data = val;
    node->lchild = nullptr;
    node->rchild = nullptr;

    if (!parent)
    {
        parent = node;
        return node;
    }

    if (parent->rchild == NULL)
    {
        parent->rchild = node;
        return node;
    }
    else if (parent->lchild == NULL)
    {
        parent ->lchild = node;
        return node;
    }
    else
    {
        return parent;
    }
}

void preorder(TNode*root)
{
    if (!root)
    {
        return;
    }
    preorder(root->lchild);
    printf("%d\n",root->data);
    preorder(root->rchild);
}

void midorder(TNode*root)
{
    if (!root)
    {
        return;
    }
    printf("%d\n",root->data);
    midorder(root->lchild);
    midorder(root->rchild);
}

void postorder(TNode*root)
{
    if (!root)
    {
        return;
    }
    postorder(root->rchild);
    printf("%d\n",root->data);
    postorder(root->lchild);
}

void layorder(TNode*root)
{
    if (!root)
    {
        return;
    }
    std::queue<TNode*>q;
    q.push(root);

    while(!q.empty())
    {
        TNode*node = q.front();
        q.pop();
        printf("%d\n",node->data);
        if (node->lchild) q.push(node->lchild);
        if (node->rchild) q.push(node->rchild);
    }
}

int main()
{
    TNode*root = new TNode;
    root ->data = 0;
    root->rchild = NULL;
    root->lchild = NULL;

    TNode*one = add_left(root,1);
    TNode*two = add_right(root,2);

    TNode*three = add_left(one,3);
    TNode*four = add_right(one,4);

    TNode*five = add_left(two,5);
    TNode*six = add_right(two,6);

    // preorder(root);
    // midorder(root);
    // postorder(root);
    layorder(root);

    return 0;
}


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

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

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

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

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

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

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

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

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

  ::CoUninitialize();
  return EXIT_SUCCESS;
}


#pragma once

/*
* SDK generated by Dumper-7
*
* https://github.com/Encryqed/Dumper-7
*/

// Package: BP_AchievementFormula

#include "Basic.hpp"

#include "BP_AchievementFormula_classes.hpp"
#include "BP_AchievementFormula_parameters.hpp"

namespace SDK
{

// Function BP_AchievementFormula.BP_AchievementFormula_C.AchTMinuteKill
// (Public, HasDefaults, BlueprintCallable, BlueprintEvent)
// Parameters:
// int32                                   AchievementID                                          (BlueprintVisible, BlueprintReadOnly, Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash)

void ABP_AchievementFormula_C::AchTMinuteKill(int32 AchievementID)
{
	static class UFunction* Func = nullptr;

	if (Func == nullptr)
		Func = Class->GetFunction("BP_AchievementFormula_C", "AchTMinuteKill");

	Params::BP_AchievementFormula_C_AchTMinuteKill Parms{};

	Parms.AchievementID = AchievementID;

	UObject::ProcessEvent(Func, &Parms);
}

// Function BP_AchievementFormula.BP_AchievementFormula_C.AchTUseVehicle
// (Public, HasDefaults, BlueprintCallable, BlueprintEvent)
// Parameters:
// int32                                   AchievementID                                          (BlueprintVisible, BlueprintReadOnly, Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash)

void ABP_AchievementFormula_C::AchTUseVehicle(int32 AchievementID)
{
	static class UFunction* Func = nullptr;

	if (Func == nullptr)
		Func = Class->GetFunction("BP_AchievementFormula_C", "AchTUseVehicle");

	Params::BP_AchievementFormula_C_AchTUseVehicle Parms{};

	Parms.AchievementID = AchievementID;

	UObject::ProcessEvent(Func, &Parms);
}

// Function BP_AchievementFormula.BP_AchievementFormula_C. AchTHPKill
// (Public, HasDefaults, BlueprintCallable, BlueprintEvent)
// Parameters:
// int32                                   AchievementID                                          (BlueprintVisible, BlueprintReadOnly, Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash)

void ABP_AchievementFormula_C::_AchTHPKill(int32 AchievementID)
{
	static class UFunction* Func = nullptr;

	if (Func == nullptr)
		Func = Class->GetFunction("BP_AchievementFormula_C", " AchTHPKill");

	Params::BP_AchievementFormula_C__AchTHPKill Parms{};

	Parms.AchievementID = AchievementID;

	UObject::ProcessEvent(Func, &Parms);
}

// Function BP_AchievementFormula.BP_AchievementFormula_C.GetSolarPlayerState
// (Public, HasOutParams, BlueprintCallable, BlueprintEvent, BlueprintPure)
// Parameters:
// class ASolarPlayerState**               OutResult                                              (Parm, OutParm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash)

void ABP_AchievementFormula_C::GetSolarPlayerState(class ASolarPlayerState** OutResult)
{
	static class UFunction* Func = nullptr;

	if (Func == nullptr)
		Func = Class->GetFunction("BP_AchievementFormula_C", "GetSolarPlayerState");

	Params::BP_AchievementFormula_C_GetSolarPlayerState Parms{};

	UObject::ProcessEvent(Func, &Parms);

	if (OutResult != nullptr)
		*OutResult = Parms.OutResult;
}

// Function BP_AchievementFormula.BP_AchievementFormula_C.GetAchievement
// (Public, HasOutParams, BlueprintCallable, BlueprintEvent, BlueprintPure)
// Parameters:
// class USolarAchievementComponent**      AchievementComponent                                   (Parm, OutParm, ZeroConstructor, InstancedReference, IsPlainOldData, NoDestructor, HasGetValueTypeHash)

void ABP_AchievementFormula_C::GetAchievement(class USolarAchievementComponent** AchievementComponent)
{
	static class UFunction* Func = nullptr;

	if (Func == nullptr)
		Func = Class->GetFunction("BP_AchievementFormula_C", "GetAchievement");

	Params::BP_AchievementFormula_C_GetAchievement Parms{};

	UObject::ProcessEvent(Func, &Parms);

	if (AchievementComponent != nullptr)
		*AchievementComponent = Parms.AchievementComponent;
}

// Function BP_AchievementFormula.BP_AchievementFormula_C.GetPlayerData
// (Public, HasOutParams, BlueprintCallable, BlueprintEvent, BlueprintPure)
// Parameters:
// class UPlayerStatisticsData**           Out                                                    (Parm, OutParm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash)

void ABP_AchievementFormula_C::GetPlayerData(class UPlayerStatisticsData** Out)
{
	static class UFunction* Func = nullptr;

	if (Func == nullptr)
		Func = Class->GetFunction("BP_AchievementFormula_C", "GetPlayerData");

	Params::BP_AchievementFormula_C_GetPlayerData Parms{};

	UObject::ProcessEvent(Func, &Parms);

	if (Out != nullptr)
		*Out = Parms.Out;
}

// Function BP_AchievementFormula.BP_AchievementFormula_C.GetSolarGameState
// (Public, HasOutParams, BlueprintCallable, BlueprintEvent, BlueprintPure)
// Parameters:
// class ASolarGameState**                 Out                                                    (Parm, OutParm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash)

void ABP_AchievementFo


#pragma once
#include <atomic>
#include <cstddef>
#include <algorithm>

class LockFreeAudioFifo
{
public:
    explicit LockFreeAudioFifo(size_t capacitySamples)
        : capacity(nextPowerOfTwo(std::max<size_t>(1024, capacitySamples))),
          mask(capacity - 1),
          buffer(new float[capacity])
    {
        writeIndex.store(0);
        readIndex.store(0);
    }

    ~LockFreeAudioFifo() { delete[] buffer; }

    // SPSC: producer (audio thread)
    void push(const float* src, int count)
    {
        size_t w = writeIndex.load(std::memory_order_relaxed);
        size_t r = readIndex.load(std::memory_order_acquire);
        size_t freeSpace = capacity - (w - r);
        size_t toWrite = (size_t) std::min<int>(count, (int)(freeSpace));
        if (toWrite == 0) return;

        for (size_t i = 0; i < toWrite; ++i)
            buffer[(w + i) & mask] = src[i];

        writeIndex.store(w + toWrite, std::memory_order_release);
    }

    // SPSC: consumer (render thread)
    int pop(float* dst, int maxCount)
    {
        size_t r = readIndex.load(std::memory_order_relaxed);
        size_t w = writeIndex.load(std::memory_order_acquire);
        size_t available = w - r;
        size_t toRead = (size_t) std::min<int>(maxCount, (int) available);
        if (toRead == 0) return 0;

        for (size_t i = 0; i < toRead; ++i)
            dst[i] = buffer[(r + i) & mask];

        readIndex.store(r + toRead, std::memory_order_release);
        return (int) toRead;
    }

    void reset()
    {
        readIndex.store(0, std::memory_order_relaxed);
        writeIndex.store(0, std::memory_order_relaxed);
    }

private:
    static size_t nextPowerOfTwo(size_t v)
    {
        if (v == 0) return 1;
        --v;
        v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v |= v >> 32;
        return v + 1;
    }

    const size_t capacity;
    const size_t mask;
    float* buffer;
    std::atomic<size_t> writeIndex { 0 };
    std::atomic<size_t> readIndex  { 0 };
};


//
//  Main.cpp
//  stocks
//
//  Created by Uwe Runtemund on 01.09.2025
//  Copyright © 2025 Jameo Software. All rights reserved.
//

#include "Precompiled.hpp"

StockDatabase::StockDatabase(const jm::String& dbFile)
{
    if (sqlite3_open(dbFile.toCString().constData(), &mDb))
    {
        std::cerr << "Can't open DB: " << sqlite3_errmsg(mDb) << std::endl;
        mDb = nullptr;
    }
}

StockDatabase::~StockDatabase()
{
    if (mDb) sqlite3_close(mDb);
}

bool StockDatabase::initSchema()
{
    const char* sql =
       " CREATE TABLE IF NOT EXISTS stocks ("
       "     id INTEGER PRIMARY KEY AUTOINCREMENT,"
       "     symbol TEXT NOT NULL UNIQUE,"
       "     name TEXT,"
       "     currency TEXT"
       " );"

       " CREATE TABLE IF NOT EXISTS prices ("
       "     id INTEGER PRIMARY KEY AUTOINCREMENT,"
       "     stock_id INTEGER,"
       "     date TEXT,"
       "     open REAL,"
       "     high REAL,"
       "     low REAL,"
       "     close REAL,"
       "     volume INTEGER,"
       "     FOREIGN KEY(stock_id) REFERENCES stocks(id)"
       " );";

    char* errMsg = nullptr;
    int rc = sqlite3_exec(mDb, sql, nullptr, nullptr, &errMsg);
    if (rc != SQLITE_OK)
    {
        std::cerr << "SQL error: " << errMsg << std::endl;
        sqlite3_free(errMsg);
        return false;
    }
    return true;
}

int StockDatabase::addStock(const jm::String& symbol,
                            const jm::String& name,
                            const jm::String& currency)
{
    const char* sql = "INSERT OR IGNORE INTO stocks (symbol, name, currency) VALUES (?, ?, ?);";
    sqlite3_stmt* stmt;

    sqlite3_prepare_v2(mDb, sql, -1, &stmt, nullptr);
    sqlite3_bind_text(stmt, 1, symbol.toCString().constData(), -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 2, name.toCString().constData(), -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 3, currency.toCString().constData(), -1, SQLITE_TRANSIENT);
    sqlite3_step(stmt);
    sqlite3_finalize(stmt);

    return getStockId(symbol);
}

int StockDatabase::getStockId(const jm::String& symbol)
{
    const char* sql = "SELECT id FROM stocks WHERE symbol = ?;";
    sqlite3_stmt* stmt;
    int stockId = -1;

    sqlite3_prepare_v2(mDb, sql, -1, &stmt, nullptr);
    sqlite3_bind_text(stmt, 1, symbol.toCString().constData(), -1, SQLITE_TRANSIENT);

    if (sqlite3_step(stmt) == SQLITE_ROW)
    {
        stockId = sqlite3_column_int(stmt, 0);
    }

    sqlite3_finalize(stmt);
    return stockId;
}

bool StockDatabase::getStockData(const jm::String& symbol,
                                 jm::String& name,
                                 jm::String& currency)
{
    const char* sql = "SELECT name,currency FROM stocks WHERE symbol = ?;";
    sqlite3_stmt* stmt;
    jm::String stockName;

    sqlite3_prepare_v2(mDb, sql, -1, &stmt, nullptr);
    sqlite3_bind_text(stmt, 1, symbol.toCString().constData(), -1, SQLITE_TRANSIENT);

    bool status = false;

    if (sqlite3_step(stmt) == SQLITE_ROW)
    {
        name = jm::String((const char*)sqlite3_column_text(stmt, 0));
        currency = jm::String((const char*)sqlite3_column_text(stmt, 1));
        status = true;
    }

    sqlite3_finalize(stmt);
    return status;
}

bool StockDatabase::insertPrice(const jm::String& symbol, const PriceRecord& r)
{
    int stock_id = getStockId(symbol);
    if (stock_id < 0) return false;

    const char* sql =
       "INSERT INTO prices (stock_id, date, open, high, low, close, volume)"
       " VALUES (?, ?, ?, ?, ?, ?, ?);";

   jm::DateFormatter df=jm::DateFormatter("yyyy-MM-dd");

    sqlite3_stmt* stmt;
    sqlite3_prepare_v2(mDb, sql, -1, &stmt, nullptr);
    sqlite3_bind_int(stmt, 1, stock_id);
    sqlite3_bind_text(stmt, 2, df.format(r.date).toCString().constData(), -1, SQLITE_TRANSIENT);
    sqlite3_bind_double(stmt, 3, r.open);
    sqlite3_bind_double(stmt, 4, r.high);
    sqlite3_bind_double(stmt, 5, r.low);
    sqlite3_bind_double(stmt, 6, r.close);
    sqlite3_bind_int(stmt, 7, r.volume);

    bool success = (sqlite3_step(stmt) == SQLITE_DONE);
    sqlite3_finalize(stmt);
    return success;
}

jm::Date sqlToDate(const jm::String &date)
{
   return jm::Date(date.substring(0,4).toInt(),
                   date.substring(5,7).toInt()-1,
                   date.substring(8,10).toInt());
}

std::vector<PriceRecord> StockDatabase::getPrices(const jm::String& symbol)
{
    std::vector<PriceRecord> results;
    int stock_id = getStockId(symbol);
    if (stock_id < 0) return results;

    const char* sql =
        "SELECT date, open, high, low, close, volume"
        " FROM prices"
        " WHERE stock_id = ?"
        " ORDER BY date;";

    sqlite3_stmt* stmt;
    sqlite3_prepare_v2(mDb, sql, -1, &stmt, nullptr);
    sqlite3_bind_int(stmt, 1, stock_id);

    while (sqlite3_step(stmt) == SQLITE_ROW)
    {
        PriceRecord r;

        jm::String date = jm::String((const char*)sqlite3_column_text(stmt, 0));

        r.date = sqlToDate(date);


#include "sdcard_manager.h"
#include "core/infrastructure/logger/logger.h"
#include "config/config_loader/config_loader.h"

// Static member definitions
const char* SDCardManager::CONFIG_FILENAME = "/config.env";
bool SDCardManager::initialized = false;
int SDCardManager::sdCsPin = DEFAULT_SD_CS_PIN;

SDCardManager& SDCardManager::getInstance() {
  static SDCardManager instance;
  return instance;
}

bool SDCardManager::initialize() {
  if (initialized) return true;

  Serial_println("[SDCARD] Initializing SDCard manager...");

  // Get SD CS pin from build flags
  #ifdef SD_CS
    sdCsPin = SD_CS;
  #else
    sdCsPin = DEFAULT_SD_CS_PIN;
  #endif

  Serial_printf("[SDCARD] Using SD CS pin: %d\n", sdCsPin);

  // Initialize SD Card
  if (!SD.begin(sdCsPin)) {
    Serial_println("[SDCARD] WARNING: SD Card not available");
    Serial_println("[SDCARD] System will use SPIFFS only");
    return false;
  }

  Serial_println("[SDCARD] SD Card initialized successfully!");
  initialized = true;

  // Try to sync configuration
  syncConfigFromSD();

  return true;
}

bool SDCardManager::isSDCardAvailable() {
  if (!initialized) {
    return SD.begin(sdCsPin);
  }
  return true;
}

bool SDCardManager::syncConfigFromSD() {
  if (!isSDCardAvailable()) {
    Serial_println("[SDCARD] SD Card not available for sync");
    return false;
  }

  // Check if config exists on SD
  if (!SD.exists(CONFIG_FILENAME)) {
    Serial_println("[SDCARD] No config.env found on SD Card");
    return false;
  }

  // Check if SD config is newer
  if (!isSDConfigNewer()) {
    Serial_println("[SDCARD] SD config is not newer, skipping sync");
    return false;
  }

  Serial_println("[SDCARD] SD config is newer, syncing to SPIFFS...");

  // Open SD file
  File sdFile = SD.open(CONFIG_FILENAME, FILE_READ);
  if (!sdFile) {
    Serial_println("[SDCARD] ERROR: Failed to open SD config file");
    return false;
  }

  // Open SPIFFS file for writing
  File spiffsFile = SPIFFS.open(CONFIG_FILENAME, FILE_WRITE);
  if (!spiffsFile) {
    Serial_println("[SDCARD] ERROR: Failed to open SPIFFS config file for writing");
    sdFile.close();
    return false;
  }

  // Copy file content
  bool success = copyFile(sdFile, spiffsFile);

  // Close files
  sdFile.close();
  spiffsFile.close();

  if (success) {
    Serial_println("[SDCARD] SUCCESS: Config synced from SD to SPIFFS!");
    Serial_println("[SDCARD] New configuration loaded successfully!");
    Serial_println("[SDCARD] No restart needed - config will be loaded on next scan cycle");
  } else {
    Serial_println("[SDCARD] ERROR: Failed to sync config from SD");
  }

  return success;
}

bool SDCardManager::syncConfigToSD() {
  if (!isSDCardAvailable()) {
    Serial_println("[SDCARD] SD Card not available for sync");
    return false;
  }

  // Check if config exists on SPIFFS
  if (!SPIFFS.exists(CONFIG_FILENAME)) {
    Serial_println("[SDCARD] No config.env found on SPIFFS");
    return false;
  }

  Serial_println("[SDCARD] Syncing config from SPIFFS to SD...");

  // Open SPIFFS file
  File spiffsFile = SPIFFS.open(CONFIG_FILENAME, FILE_READ);
  if (!spiffsFile) {
    Serial_println("[SDCARD] ERROR: Failed to open SPIFFS config file");
    return false;
  }

  // Open SD file for writing
  File sdFile = SD.open(CONFIG_FILENAME, FILE_WRITE);
  if (!sdFile) {
    Serial_println("[SDCARD] ERROR: Failed to open SD config file for writing");
    spiffsFile.close();
    return false;
  }

  // Copy file content
  bool success = copyFile(spiffsFile, sdFile);

  // Close files
  spiffsFile.close();
  sdFile.close();

  if (success) {
    Serial_println("[SDCARD] SUCCESS: Config synced from SPIFFS to SD!");
  } else {
    Serial_println("[SDCARD] ERROR: Failed to sync config to SD");
  }

  return success;
}

bool SDCardManager::isSDConfigNewer() {
  if (!isSDCardAvailable() || !SD.exists(CONFIG_FILENAME)) {
    Serial_println("[SDCARD] DEBUG: SD not available or config not found");
    return false;
  }

  // Check if force sync is enabled
  if (isForceSyncEnabled()) {
    Serial_println("[SDCARD] DEBUG: Force sync enabled, treating SD as newer");
    return true;
  }

  // Open SD file
  File sdFile = SD.open(CONFIG_FILENAME, FILE_READ);
  if (!sdFile) {
    Serial_println("[SDCARD] DEBUG: Failed to open SD file");
    return false;
  }

  // Open SPIFFS file
  File spiffsFile = SPIFFS.open(CONFIG_FILENAME, FILE_READ);
  if (!spiffsFile) {
    Serial_println("[SDCARD] DEBUG: SPIFFS file not found, SD is newer");
    sdFile.close();
    return true; // SD exists but SPIFFS doesn't
  }

  sdFile.close();
  spiffsFile.close();

  // Strategy 1: Try timestamp comparison (most reliable when NTP is working)
  int timestampResult = compareByTimestamp();
  if (timestampResult != -1) { // If we got a definitive result (not "cannot determine")
    bool isNewer = (timestampResult == 1);
    Serial_printf("[SDCARD] DEBUG: Using timestamp comparison resul


#include "Cliente.h" //inclusão do arquivo que contém a definição da classe

Cliente::Cliente(string cpfCliente, string nomeCliente, int formaDePagamento, int numeroParcelas){ // construtor inicializa os métods da classe cliente

    setCpfCliente(cpfCliente);
    setNomeCliente(nomeCliente);
	setFormaDePagamento(formaDePagamento);
	setNumeroParcelas(numeroParcelas);
}

Cliente::~Cliente(){} //Destrutur

void Cliente::setCpfCliente(string cpfCliente ){ //Definição de CPF cliente.

    this -> cpfCliente = cpfCliente;

}

void Cliente::setNomeCliente(string nomeCliente){ //Definição do nome cliente.

    this -> nomeCliente = nomeCliente ;

}

string Cliente::getCpfCliente(){ //Retorna o CPF do cliente.

  return cpfCliente;

}

string Cliente::getNomeCliente(){ //Retorna o nome do cliente.

  return nomeCliente;

}

void Cliente::setFormaDePagamento(int FormaDePagamento){ //Define a forma de pagamento do cliente.

	this -> FormaDePagamento = FormaDePagamento ;
}

int Cliente::getFormaDePagamento(){

	return FormaDePagamento;
}

void Cliente::adicionarLivro(Livro livro){ //Adiciona um livro ao carrinho do cliente.

    carrinhoLivros.push_back(livro);
}

void Cliente::adicionarItem(ItemPapelaria item){ //Adiciona um item ao carrinho do cliente.

    carrinhoItens.push_back(item);
}

bool Cliente::removerProduto(string nome, int opcao, int quantidade) { //remove um produto do carrinho do cliente.
    int posicao_produto = -1;  //Inicializa a posição como inválida

    switch (opcao) {
        case 1:
            for (int a = 0; a < carrinhoLivros.size(); a++) {

                if (carrinhoLivros[a].getNome() == nome) {

                    posicao_produto = a;
                    if (quantidade == carrinhoLivros[a].getQuantidade()) {

                        // Se a quantidade digitada for igual à quantidade total de livros no carrinh removerá todo o produto
                        carrinhoLivros.erase(carrinhoLivros.begin() + a);
                    } else {
                        // Caso contrário, apenas diminui a quantidade no carrinho
                        carrinhoLivros[a].setQuantidade(carrinhoLivros[a].getQuantidade() - quantidade);
                    }
                    break;  // Encontrou o livro, não precisa continuar o loop
                }
            }
            break;

        case 2: //Se o usuário escolheu 2(Opção para Item Papelaria)... Realize os comandos abaixo
            for (int b = 0; b < carrinhoItens.size(); b++) {
                if (carrinhoItens[b].getNome() == nome) {
                    posicao_produto = b;//A variável posicao_produto é atualizada com o índice do elemento encontrado.

                    if (quantidade == carrinhoItens[b].getQuantidade()) {
                        // Se a quantidade a ser removida é igual à quantidade total, remove o produto
                        carrinhoItens.erase(carrinhoItens.begin() + b);
                    } else {
                        // Caso contrário, apenas diminui a quantidade
                        carrinhoItens[b].setQuantidade(carrinhoItens[b].getQuantidade() - quantidade);
                    }
                    break;  // Encontrou o item, não precisa continuar o loop
                }
            }
            break;

        default:
            cout << endl << endl;
            cout << "-------Opção Inválida-------" << endl;
            cout << endl << endl;
    }

    return posicao_produto != -1;  // Retorna verdadeiro se o produto foi encontrado e removido
}

float Cliente::valorTotal(){ //retorna o valor total do carrinho do cliente.

//Criação de variáveis para armazenar os valores totais dos livros e dos itens da papelaria
	float valor_aux2 = 0.0;
	float valor_aux3 = 0.0;

// loop usado para percorrer o vetor de livros
	for(int i = 0; i < carrinhoLivros.size(); i++)
    {
    	valor_aux2 += carrinhoLivros[i].getPreco() * carrinhoLivros[i].getQuantidade();
    }

  	for(int j = 0; j < carrinhoItens.size(); j++)
    {
    	valor_aux3 += carrinhoItens[j].getPreco() * carrinhoItens[j].getQuantidade();

    }

	return valor_aux2 + valor_aux3; // retorna a soma do valor total dos livros e o valor total dos itens
}

void Cliente::exibirCarrinho(){ //exibe o conteúdo do carrinho do cliente.

    int i, j;

    cout << endl << endl << "Produtos do seu carrinho de compras: " << endl << endl;

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

            cout << "- Item Livraria: " << carrinhoLivros[i].getNome() << endl;
            cout << "- Nome do autor: " << carrinhoLivros[i].getAutor() << endl;
            cout << "- Quantidade no carrinho: " << carrinhoLivros[i].getQuantidade() << endl;
            cout << "- Valor: R$" << carrinhoLivros[i].getPreco() << endl << endl;

        }

        for(j = 0; j < carrinhoItens.size(); j++){

            cout << "- Item de Papelaria:" << carrinhoItens[j].getNome() << endl;
            cout << "- Quantidade no carrinho: " << carrinhoItens[


#include "listmateriels.h"
#include "ui_listmateriels.h"
#include "connectbdd.h"
#include "modifmat.h"
#include "entretientmateriels.h"
#include "detailsmateriels.h"
#include "error.h"
#include "modifentretientmateriels.h"
#include "mainwindow.h"
#include "facture.h"

#include <QPropertyAnimation>
#include <QMouseEvent>
#include <iostream>
#include <QWidget>
#include <QString>
#include <QSqlQuery>
#include <QMessageBox>
#include <QStandardItemModel>
#include <QStandardItem>
#include <QIcon>

using namespace std;

ListMateriels::ListMateriels(int Matricule, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ListMateriels)
{
    ui->setupUi(this);
    this->setWindowTitle("GESTION DES MATÉRIELS");
    resize(1000,450);
    this->matriculeUtilisateurGlobal = Matricule; // initialise le matricule pour le lié avec celle dans la fenêtre de connection..
    bienvenueUtil(matriculeUtilisateurGlobal); // Appel du fonction Bienvenue

    ui->ajoutMat->setStyleSheet(qstyle.one);
    ui->zonederecherche->setStyleSheet(qstyle.zoneRecherche);
    ui->BttnListIntervenant->setStyleSheet(qstyle.BttnGauche);
    ui->listmatEntretenu->setStyleSheet(qstyle.BttnGauche);
    ui->retourBttn->setStyleSheet(qstyle.changeUtil);
    ui->quiterBttn->setStyleSheet(qstyle.quitU);

    ui->quiterBttn->installEventFilter(this); // Quand le souris passe par le boutton quitter
    ui->BttnListIntervenant->installEventFilter(this);
    ui->listmatEntretenu->installEventFilter(this);

    // Intégration des icons dans les bouttons
    ui->listmatEntretenu->setIcon(QIcon(":/images/Images/fix-work-repair-system-svgrepo-com.svg"));
    ui->listmatEntretenu->setIconSize(QSize(50,50));
    ui->BttnListIntervenant->setIcon(QIcon(":/images/Images/list-1422-svgrepo-com.svg"));
    ui->BttnListIntervenant->setIconSize(QSize(50,50));
    ui->detailsMat->setIcon(QIcon(":/images/Images/details-block-svgrepo-com.svg"));
    ui->detailsMat->setIconSize(QSize(20,20));
    ui->retourBttn->setIcon(QIcon(":/images/Images/logout-svgrepo-com.svg"));
    ui->retourBttn->setIconSize(QSize(30,30));
    ui->quiterBttn->setIcon(QIcon(":/images/Images/system-shutdown-panel-svgrepo-com.svg"));
    ui->quiterBttn->setIconSize(QSize(30,30));

    // Figé les bouttons
    ui->modifMat->setDisabled(true);
    ui->supprimMat->setDisabled(true);
    ui->IntervenirMat->setDisabled(true);
    ui->supprimerMatEntretenu->setDisabled(true);
    ui->factureBttn->setEnabled(false);

    ui->viewIntervenantVide->setHidden(true);

    afficheIntervenants();
    afficheListeIntervention();
    afficheMateriels();
}

ListMateriels::~ListMateriels()
{
    delete ui;
}

bool ListMateriels::eventFilter(QObject *obj, QEvent *evenm) // Fonction pour modifier les bouttons au survol
{
    if (obj == ui->quiterBttn) {
        if (evenm->type() == QEvent::Enter) {
            ui->quiterBttn->setText("QUITTER");
            ui->quiterBttn->setStyleSheet(qstyle.quitUtil);
            ui->quiterBttn->setIconSize(QSize(20,20));
        } else if (evenm->type() == QEvent::Leave){
            ui->quiterBttn->setText("");
            ui->quiterBttn->setIconSize(QSize(30,30));
            ui->quiterBttn->setStyleSheet(qstyle.quitU);
        }
    } else if (obj == ui->BttnListIntervenant) {
        if (evenm->type() == QEvent::Enter) {
            ui->BttnListIntervenant->setText("INTERVENANTS");
            ui->BttnListIntervenant->setIconSize(QSize(30,30));
        } else if (evenm->type() == QEvent::Leave) {
            ui->BttnListIntervenant->setText("");
            ui->BttnListIntervenant->setIconSize(QSize(50,50));
        }
    } else if (obj == ui->listmatEntretenu) {
        if (evenm->type() == QEvent::Enter) {
            ui->listmatEntretenu->setText("ENTRETIENTS");
            ui->listmatEntretenu->setIconSize(QSize(50,30));
        } else if (evenm->type() == QEvent::Leave) {
            ui->listmatEntretenu->setText("");
            ui->listmatEntretenu->setIconSize(QSize(50,50));
        }
    }
    return QDialog::eventFilter(obj, evenm);
}

void ListMateriels::bienvenueUtil(int matr) // MESSAGE DE BIENVENUE
{
    connectbdd bdd;
    bdd.mivohabdd();
    QSqlQuery querybvn;
    querybvn.prepare("SELECT PseudoUtilisateur FROM Utilisateurs WHERE Matricule=:matricule;");
    querybvn.bindValue(":matricule", matr);
    if (querybvn.exec()) {
        if (querybvn.next()) {
            qDebug() << "BIENVENUE : " << matr;
            ui->LabelBienvenue->setText("
Bienvenue "+querybvn.value(0).toString()+"
"); // Prise du Pseudo
            bdd.mihidybdd();
        } else qDebug() << "tsisy eh...";
    } else {
        qDebug() << "ERREUR DE BIENVENUE : " <<querybvn.lastError();
    }
}

void ListMateriels::on_ajoutMat_clicked() // AJOUT matériels
{
    cout << "mampidira materiel.." << endl;
    mat = new materiel(matriculeUtilisateurGlobal); // paramétrer "matriculeGlobal dans la fenêtre materiel
    mat->setModal(t