dc420c3b7a
2. 顺便完善了底层通信类的封装,基于websocket,基准测试通过,但存在一点很小的线程bug,似乎是来自于esp32 idf底层的问题,待解决
306 lines
9.6 KiB
C++
306 lines
9.6 KiB
C++
//
|
|
// Created by misaki on 2025/9/14.
|
|
//
|
|
|
|
#include "PetDao.h"
|
|
#include <iostream>
|
|
#include <sstream>
|
|
|
|
using namespace PetEnumConverter;
|
|
|
|
// PetEnumConverter 实现
|
|
std::string PetEnumConverter::stageTypeToString(PetStageType stage) {
|
|
switch (stage) {
|
|
#define X(name, desc) case PetStageType::name: return #name;
|
|
PET_STAGE_TYPES
|
|
#undef X
|
|
default: return "UNKNOWN";
|
|
}
|
|
}
|
|
|
|
PetStageType PetEnumConverter::stringToStageType(const std::string& str) {
|
|
#define X(name, desc) if (str == #name) return PetStageType::name;
|
|
PET_STAGE_TYPES
|
|
#undef X
|
|
return PetStageType::PET_STAGE_YOUNG; // 默认值
|
|
}
|
|
|
|
std::string PetEnumConverter::actionTypeToString(PetActionType action) {
|
|
switch (action) {
|
|
#define X(name, desc) case PetActionType::name: return #name;
|
|
PET_ACTION_TYPES
|
|
#undef X
|
|
default: return "UNKNOWN";
|
|
}
|
|
}
|
|
|
|
PetActionType PetEnumConverter::stringToActionType(const std::string& str) {
|
|
#define X(name, desc) if (str == #name) return PetActionType::name;
|
|
PET_ACTION_TYPES
|
|
#undef X
|
|
return PetActionType::PET_ACTION_SLEEP; // 默认值
|
|
}
|
|
|
|
// PetDAO 实现
|
|
PetDAO::PetDAO(SDFileManager* fileManager) : fileManager(fileManager) {
|
|
// 确保宠物数据目录存在
|
|
fileManager->mkdirCommand( PET_DATA_DIR);
|
|
}
|
|
|
|
bool PetDAO::savePet(const std::shared_ptr<PetBase>& pet, const std::string& filename) {
|
|
// 转换为JSON
|
|
cJSON* json = petToJson(pet);
|
|
if (!json) {
|
|
return false;
|
|
}
|
|
|
|
// 转换为字符串
|
|
char* jsonStr = cJSON_PrintUnformatted(json);
|
|
std::string fullPath = std::string(PET_DATA_DIR) + "/" + filename;
|
|
|
|
// 保存到文件
|
|
bool success = fileManager->writeFileSync(fullPath.c_str(), jsonStr);
|
|
|
|
// 清理资源
|
|
free(jsonStr);
|
|
cJSON_Delete(json);
|
|
|
|
return success;
|
|
}
|
|
|
|
std::shared_ptr<PetBase> PetDAO::loadPet(const std::string& filename) {
|
|
std::string fullPath = std::string(PET_DATA_DIR) + "/" + filename;
|
|
|
|
// 读取文件内容
|
|
std::string content = fileManager->readFileSync(fullPath.c_str());
|
|
if (content.empty()) {
|
|
return nullptr;
|
|
}
|
|
|
|
// 解析JSON
|
|
cJSON* json = cJSON_Parse(content.c_str());
|
|
if (!json) {
|
|
return nullptr;
|
|
}
|
|
|
|
// 创建宠物对象
|
|
auto pet = petFromJson(json);
|
|
|
|
// 清理资源
|
|
cJSON_Delete(json);
|
|
|
|
return pet;
|
|
}
|
|
|
|
std::vector<std::string> PetDAO::listPetFiles() {
|
|
return fileManager->listFilesSync(PET_DATA_DIR, ".json");
|
|
}
|
|
|
|
bool PetDAO::deletePetFile(const std::string& filename) {
|
|
std::string fullPath = std::string(PET_DATA_DIR) + "/" + filename;
|
|
return fileManager->rmCommand(fullPath.c_str(), false);
|
|
}
|
|
|
|
cJSON* PetDAO::petToJson(const std::shared_ptr<PetBase>& pet) {
|
|
cJSON* json = cJSON_CreateObject();
|
|
if (!json) return nullptr;
|
|
|
|
// 添加基本信息
|
|
cJSON_AddStringToObject(json, "name", pet->pet_info.pet_name.c_str());
|
|
cJSON_AddNumberToObject(json, "hp", pet->pet_info.pet_hp);
|
|
cJSON_AddNumberToObject(json, "density", pet->pet_info.pet_density);
|
|
cJSON_AddStringToObject(json, "identity", pet->pet_info.pet_identity.c_str());
|
|
|
|
// 添加阶段策略
|
|
cJSON* stageJson = stageStrategyToJson(pet->pet_stage_strategy);
|
|
if (stageJson) {
|
|
cJSON_AddItemToObject(json, "stage_strategy", stageJson);
|
|
}
|
|
|
|
// 添加动作策略
|
|
cJSON* actionJson = actionStrategyToJson(pet->pet_action_strategy);
|
|
if (actionJson) {
|
|
cJSON_AddItemToObject(json, "action_strategy", actionJson);
|
|
}
|
|
|
|
return json;
|
|
}
|
|
|
|
std::shared_ptr<PetBase> PetDAO::petFromJson(cJSON* json) {
|
|
if (!json) return nullptr;
|
|
|
|
// 创建宠物基本信息
|
|
PetBaseInfo info;
|
|
cJSON* nameItem = cJSON_GetObjectItemCaseSensitive(json, "name");
|
|
if (cJSON_IsString(nameItem)) {
|
|
info.pet_name = nameItem->valuestring;
|
|
}
|
|
|
|
cJSON* hpItem = cJSON_GetObjectItemCaseSensitive(json, "hp");
|
|
if (cJSON_IsNumber(hpItem)) {
|
|
info.pet_hp = hpItem->valueint;
|
|
}
|
|
|
|
cJSON* densityItem = cJSON_GetObjectItemCaseSensitive(json, "density");
|
|
if (cJSON_IsNumber(densityItem)) {
|
|
info.pet_density = densityItem->valueint;
|
|
}
|
|
|
|
cJSON* identityItem = cJSON_GetObjectItemCaseSensitive(json, "identity");
|
|
if (cJSON_IsString(identityItem)) {
|
|
info.pet_identity = identityItem->valuestring;
|
|
}
|
|
|
|
// 创建阶段策略
|
|
cJSON* stageJson = cJSON_GetObjectItemCaseSensitive(json, "stage_strategy");
|
|
auto stageStrategy = stageStrategyFromJson(stageJson);
|
|
|
|
// 创建动作策略
|
|
cJSON* actionJson = cJSON_GetObjectItemCaseSensitive(json, "action_strategy");
|
|
auto actionStrategy = actionStrategyFromJson(actionJson);
|
|
|
|
// 创建宠物对象
|
|
return std::make_shared<PetBase>(info, stageStrategy, actionStrategy);
|
|
}
|
|
|
|
cJSON* PetDAO::stageStrategyToJson(const std::shared_ptr<PetStageStrategy>& strategy) {
|
|
if (!strategy) return nullptr;
|
|
|
|
cJSON* json = cJSON_CreateObject();
|
|
if (!json) return nullptr;
|
|
|
|
// 添加当前阶段
|
|
cJSON_AddStringToObject(json, "current_stage",
|
|
stageTypeToString(strategy->getCurrentStageType()).c_str());
|
|
|
|
// 添加阶段模型映射
|
|
cJSON* modelMap = cJSON_CreateObject();
|
|
for (const auto& pair : strategy->getStageModelMap()) {
|
|
cJSON_AddStringToObject(modelMap,
|
|
stageTypeToString(pair.first).c_str(),
|
|
pair.second.c_str());
|
|
}
|
|
cJSON_AddItemToObject(json, "stage_model_map", modelMap);
|
|
|
|
// 添加阶段音频映射
|
|
cJSON* audioMap = cJSON_CreateObject();
|
|
for (const auto& pair : strategy->getStageAudioMap()) {
|
|
cJSON_AddStringToObject(audioMap,
|
|
stageTypeToString(pair.first).c_str(),
|
|
pair.second.c_str());
|
|
}
|
|
cJSON_AddItemToObject(json, "stage_audio_map", audioMap);
|
|
|
|
return json;
|
|
}
|
|
|
|
std::shared_ptr<PetStageStrategy> PetDAO::stageStrategyFromJson(cJSON* json) {
|
|
if (!json) return nullptr;
|
|
|
|
auto strategy = std::make_shared<PetStageStrategy>();
|
|
|
|
// 获取当前阶段
|
|
cJSON* currentStageItem = cJSON_GetObjectItemCaseSensitive(json, "current_stage");
|
|
if (cJSON_IsString(currentStageItem)) {
|
|
strategy->current_stage = stringToStageType(currentStageItem->valuestring);
|
|
}
|
|
|
|
// 获取阶段模型映射
|
|
cJSON* modelMapItem = cJSON_GetObjectItemCaseSensitive(json, "stage_model_map");
|
|
if (cJSON_IsObject(modelMapItem)) {
|
|
cJSON* child = modelMapItem->child;
|
|
while (child) {
|
|
if (cJSON_IsString(child)) {
|
|
PetStageType stage = stringToStageType(child->string);
|
|
strategy->stage_model_map[stage] = child->valuestring;
|
|
}
|
|
child = child->next;
|
|
}
|
|
}
|
|
|
|
// 获取阶段音频映射
|
|
cJSON* audioMapItem = cJSON_GetObjectItemCaseSensitive(json, "stage_audio_map");
|
|
if (cJSON_IsObject(audioMapItem)) {
|
|
cJSON* child = audioMapItem->child;
|
|
while (child) {
|
|
if (cJSON_IsString(child)) {
|
|
PetStageType stage = stringToStageType(child->string);
|
|
strategy->stage_audio_map[stage] = child->valuestring;
|
|
}
|
|
child = child->next;
|
|
}
|
|
}
|
|
|
|
return strategy;
|
|
}
|
|
|
|
cJSON* PetDAO::actionStrategyToJson(const std::shared_ptr<PetActionStrategy>& strategy) {
|
|
if (!strategy) return nullptr;
|
|
|
|
cJSON* json = cJSON_CreateObject();
|
|
if (!json) return nullptr;
|
|
|
|
// 添加当前动作
|
|
cJSON_AddStringToObject(json, "current_action",
|
|
actionTypeToString(strategy->getCurrentActionType()).c_str());
|
|
|
|
// 添加动作模型映射
|
|
cJSON* modelMap = cJSON_CreateObject();
|
|
for (const auto& pair : strategy->getActionModelMap()) {
|
|
cJSON_AddStringToObject(modelMap,
|
|
actionTypeToString(pair.first).c_str(),
|
|
pair.second.c_str());
|
|
}
|
|
cJSON_AddItemToObject(json, "action_model_map", modelMap);
|
|
|
|
// 添加动作音频映射
|
|
cJSON* audioMap = cJSON_CreateObject();
|
|
for (const auto& pair : strategy->getActionAudioMap()) {
|
|
cJSON_AddStringToObject(audioMap,
|
|
actionTypeToString(pair.first).c_str(),
|
|
pair.second.c_str());
|
|
}
|
|
cJSON_AddItemToObject(json, "action_audio_map", audioMap);
|
|
|
|
return json;
|
|
}
|
|
|
|
std::shared_ptr<PetActionStrategy> PetDAO::actionStrategyFromJson(cJSON* json) {
|
|
if (!json) return nullptr;
|
|
|
|
auto strategy = std::make_shared<PetActionStrategy>();
|
|
|
|
// 获取当前动作
|
|
cJSON* currentActionItem = cJSON_GetObjectItemCaseSensitive(json, "current_action");
|
|
if (cJSON_IsString(currentActionItem)) {
|
|
strategy->current_action = stringToActionType(currentActionItem->valuestring);
|
|
}
|
|
|
|
// 获取动作模型映射
|
|
cJSON* modelMapItem = cJSON_GetObjectItemCaseSensitive(json, "action_model_map");
|
|
if (cJSON_IsObject(modelMapItem)) {
|
|
cJSON* child = modelMapItem->child;
|
|
while (child) {
|
|
if (cJSON_IsString(child)) {
|
|
PetActionType action = stringToActionType(child->string);
|
|
strategy->action_model_map[action] = child->valuestring;
|
|
}
|
|
child = child->next;
|
|
}
|
|
}
|
|
|
|
// 获取动作音频映射
|
|
cJSON* audioMapItem = cJSON_GetObjectItemCaseSensitive(json, "action_audio_map");
|
|
if (cJSON_IsObject(audioMapItem)) {
|
|
cJSON* child = audioMapItem->child;
|
|
while (child) {
|
|
if (cJSON_IsString(child)) {
|
|
PetActionType action = stringToActionType(child->string);
|
|
strategy->action_audio_map[action] = child->valuestring;
|
|
}
|
|
child = child->next;
|
|
}
|
|
}
|
|
|
|
return strategy;
|
|
} |