独立游戏《星尘异变》UE5 C++程序开发日志5——实现物流系统

目录

一、进出口清单

二、路径计算

 三、包裹

1.包裹的数据结构

 2.包裹在场景中的运动

四、道路

1.道路的数据结构

2.道路的建造

3.道路的销毁

4.某个有道路连接的建筑被删除


        作为一个工厂类模拟经营游戏,各个工厂之间的运输必不可少,本游戏采用的是按需进口的模式,工厂之间可以建立类似于传送带一样的直连道路,每个工厂根据自身当前缺少的所需物品,按照从近到远的顺序依次访问能够生产该物品的工厂,然后收到出口订单的工厂会发出包裹,沿着玩家建设的道路送达发出进口需求的工厂,玩家可以手动配置进出口清单,也就是工厂仓库中某类物品少于多少个就要进口,以及某类物品多于多少个才可以出口,效果如下:

一、进出口清单

         玩家可以编辑每一个建筑的进出口清单实现对进出口的调控,即库存少于多少进口,多于多少出口。清单是一个数组,包括物品的种类和数量,同时还有自动和手动计算的功能切换,在自动模式下,清单中的数值即为生产时实际需求的原料数量,在改为手动模式后,对应物品的数量等于上次手动设置过的数量,清单数组中的数据结构如下:

USTRUCT(BlueprintType)
struct FImportStardust
{FImportStardust(const FName& StardustId, const int Quantity): StardustId(StardustId),Quantity(Quantity){}GENERATED_BODY()UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Import")FName StardustId{ "Empty" };UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Import")int Quantity{ 0 };//是否手动更新数量UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Import")bool IsAuto{true};//上一次手动设定的值UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Import")int LastManualSet{0};FImportStardust()=default;
};

        设置清单中某类星尘的数量:

bool ABP_Asters::SetElementInImportingStardust(const int& Index, const int& Amount)
{//检查索引是否合法if(Index<0||Index>=ImportingStardust.Num()){UE_LOG(LogTemp,Error,TEXT("SetElementInImportingStardust failed,invalid index:%d"),Index);return false;}ImportingStardust[Index].Quantity=Amount;//维护上一次手动设置的值if(!ImportingStardust[Index].IsAuto){ImportingStardust[Index].LastManualSet=Amount;}return true;
}

设置某类星尘的计算是否手动:

void ABP_Asters::SetIsAutoInImportingStardust(const int& Index, const bool& IsAuto)
{//检查索引是否合法if(Index<0||Index>=ImportingStardust.Num()){UE_LOG(LogTemp,Error,TEXT("SetIsAutoInImportingStardust failed,invalid index:%d"),Index);return;}ImportingStardust[Index].IsAuto=IsAuto;if(IsAuto){ImportingStardust[Index].LastManualSet=ImportingStardust[Index].Quantity;//计算某类星尘的需求量
ImportingStardust[Index].Quantity=CalCulateReactionConsumption(ImportingStardust[Index].StardustId);}else{ImportingStardust[Index].Quantity=ImportingStardust[Index].LastManualSet;}
}

二、路径计算

        我们的物流是由进口需求引导的,所以寻路也是由某一个建筑出发,依次遍历连通的最近的建筑来尝试从其进口需要的物品,路径为从出口天体到该天体的路径

TArray<FStardustBasic> ATradingSystemActor::TriggerImport(const int& SourceAsterIndex, const TArray<FStardustBasic> ImportingStardust)
{//输入进口源天体的索引和需求的星尘,返回有哪些进口需求未被满足//检查输入索引是否合法if(!DebugActor->AllAster.Find(SourceAsterIndex)){UE_LOG(LogTemp,Error,TEXT("TriggerImport failed,invalid index:%d"),SourceAsterIndex);return TArray<FStardustBasic>();}std::unordered_map<std::string,int>StardustNeed;for(const auto& it:ImportingStardust){StardustNeed[TCHAR_TO_UTF8(*it.StardustId.ToString())]=it.Quantity;}//建立一个dijkstra算法使用的节点结构,包含点的ID和到起点距离struct Node{Node(const int& ID, const long long& DIstance): ID(ID),DIstance(DIstance){}Node(const Node& Other):ID(Other.ID),DIstance(Other.DIstance){}int ID;long long DIstance;};//重载优先队列排序规则auto cmp{[](const TSharedPtr<Node>&a,const TSharedPtr<Node>& b){return a->DIstance>b->DIstance;}};//储存当前待遍历的点的优先队列,按到起点路径长度从小到大排序
std::priority_queue<TSharedPtr<Node>,std::vector<TSharedPtr<Node>>,decltype(cmp)>Queue(cmp);//放入起点Queue.push(MakeShared<Node>(SourceAsterIndex, 0));//起点到每一个点的最短距离std::map<int,long long>MinimumDistance;//每个点是否被处理完毕std::map<int,bool>Done;//储存最短路径中每个点的父节点std::map<int,int>Path;for(auto& it:DebugActor->AllAster){//初始化最短距离为极大值MinimumDistance[it.Key]=1e18;Done[it.Key]=false;}MinimumDistance[SourceAsterIndex]=0;while(!Queue.empty()){auto Current{Queue.top()};Queue.pop();if(Done[Current->ID]){continue;}if(Current->ID!=SourceAsterIndex){if(!DebugActor->AllAster.Find(Current->ID)){continue;}//当前遍历到的天体auto FoundedAster{DebugActor->AllAster[Current->ID]};TArray<FStardustBasic>PackgingStardust;//遍历出口清单for(const auto&it:FoundedAster->GetExportingStardust()){std::string IDString{TCHAR_TO_UTF8(*it.StardustId.ToString())};if(StardustNeed.find(IDString)==StardustNeed.end()||!StardustNeed[IDString]){continue;}//找到的天体可出口的星尘数量int Available{FoundedAster->OutputInventory->CheckStardust(it.StardustId)-it.Quantity};//实际出口的数量if(int Transfered{std::max(0,std::min(StardustNeed[IDString],Available))}){//维护当前包裹中的星尘和天体仓库中的星尘PackgingStardust.Add(FStardustBasic(it.StardustId,Transfered));FoundedAster->OutputInventory->RemoveStardust(it.StardustId,Transfered);StardustNeed[IDString]-=Transfered;if(!StardustNeed[IDString]){StardustNeed.erase(IDString);}}}//该天体进行了出口if(!PackgingStardust.IsEmpty()){TArray<int>PassedAsters;int CurrentPosition{Current->ID};//记录该天体到进口需求发出天体的路径while (CurrentPosition!=SourceAsterIndex){CurrentPosition=Path[CurrentPosition];PassedAsters.Add(CurrentPosition);}TArray<int>PassedAsters2;//使路径从后往前为包裹要走过的天体for(int i=PassedAsters.Num()-1;i>=0;i--){PassedAsters2.Add(PassedAsters[i]);}//令目标天体发送包裹SendPackage(FPackageInformation(Current->ID,PassedAsters2,PackgingStardust));//所有进口需求都被满足,提前终止if(StardustNeed.empty()){return TArray<FStardustBasic>();}}}//该天体处理完毕,防止被再次处理Done[Current->ID]=true;//遍历该天体所有联通的天体for(const auto&it:AsterGraph[Current->ID]){if(Done[it->TerminalIndex])continue;//这条路是最短路if(MinimumDistance[it->TerminalIndex]>it->distance+Current->DIstance){Path[it->TerminalIndex]=Current->ID;//更新最短路径MinimumDistance[it->TerminalIndex]=it->distance+Current->DIstance;Queue.push(MakeShared<Node>(it->TerminalIndex,MinimumDistance[it->TerminalIndex]));}}}//返回未满足的进口需求TArray<FStardustBasic> Result;if(!StardustNeed.empty()){for(const auto&it:StardustNeed){Result.Add(FStardustBasic(FName(UTF8_TO_TCHAR(it.first.c_str())),it.second));}}return Result;
}

重新寻路的逻辑与之类似,区别在于只是搜索确定的两点之间的最短路,不会发送包裹:

TArray<int> ATradingSystemActor::ReRoute(const int& Start, const int& end)
{TArray<int>Result;struct Node{Node(const int ID, const int DIstance): ID(ID),DIstance(DIstance){}int ID;long long DIstance;};auto cmp{[](const TSharedPtr<Node>&a,const TSharedPtr<Node>& b){return a->DIstance>b->DIstance;}};std::priority_queue<TSharedPtr<Node>,std::vector<TSharedPtr<Node>>,decltype(cmp)>Queue(cmp);Queue.push(MakeShared<Node>(Start,0));std::unordered_map<int,long long>MinimumDistance;std::unordered_map<int,bool>Done;std::map<int,int>Path;for(auto& it:DebugActor->AllAster){MinimumDistance[it.Key]=1e18;Done[it.Key]=false;}MinimumDistance[0]=0;while(!Queue.empty()){auto Current{Queue.top()};Queue.pop();if(Done[Current->ID]){continue;}Done[Current->ID]=true;for(const auto&it:AsterGraph[Current->ID]){//找到终点立刻终止运算if(it->TerminalIndex==end){TArray<int>PassedAsters;int CurrentPosition{Current->ID};while (CurrentPosition!=Start){CurrentPosition=Path[CurrentPosition];PassedAsters.Add(CurrentPosition);}TArray<int>PassedAsters2;for(int i=PassedAsters.Num()-1;i>=0;i--){PassedAsters2.Add(PassedAsters[i]);}return PassedAsters2;}if(Done[it->TerminalIndex])continue;if(MinimumDistance[it->TerminalIndex]>it->distance+Current->DIstance){Path[it->TerminalIndex]=Current->ID;MinimumDistance[it->TerminalIndex]=it->distance+Current->DIstance;Queue.push(MakeShared<Node>(it->TerminalIndex,MinimumDistance[it->TerminalIndex]));}}}//没找到路径返回的是空数组return Result;
}

 三、包裹

1.包裹的数据结构

        包裹的数据包裹发出该包裹的建筑的索引,计划要经过的所有建筑的索引,和携带的星尘

USTRUCT(BlueprintType)
struct FPackageInformation
{explicit  FPackageInformation(const int SourceAsterIndex, const TArray<int>& ExpectedPath,const TArray<FStardustBasic>&ExpectedStardusts): SourceAsterIndex(SourceAsterIndex),ExpectedPath(ExpectedPath),Stardusts(ExpectedStardusts){}FPackageInformation() = default;GENERATED_BODY()//发出包裹的源天体UPROPERTY(VisibleAnywhere,BlueprintReadWrite,Category="Package")int SourceAsterIndex{0};//计划的路径,从后到前依次为即将走过的天体索引UPROPERTY(VisibleAnywhere,BlueprintReadWrite,Category="Package")TArray<int> ExpectedPath;//包裹携带的星尘UPROPERTY(VisibleAnywhere,BlueprintReadWrite,Category="Package")TArray<FStardustBasic>Stardusts;
};

 2.包裹在场景中的运动

            每个包裹的路径是在其生成时就计算好的,数组中从后到前依次是其计划经过的建筑的索引,每到达一个建筑后将末尾的元素弹出,直到全部弹出即到达终点

bool APackageActor::AsterReached(const int& AsterIndex)
{//检查输入的天体索引是否真实存在if(!TradingSystem->DebugActor->AllAster.Find(AsterIndex)){UE_LOG(LogTemp,Error,TEXT("AsterReached failed,invalid index:%d"),AsterIndex);return false;}//即将到达终点if(PackgeInfo.ExpectedPath.Num()==1){//送达包裹中的星尘for(auto&it:PackgeInfo.Stardusts){TradingSystem->DebugActor->AllAster[AsterIndex]->InputInventory->AddStardust(it.StardustId,it.Quantity);it.Quantity-=std::min(it.Quantity,TradingSystem->DebugActor->AllAster[AsterIndex]->InputInventory->CheckAddable(it.StardustId));}//更新库存UITradingSystem->DebugActor->AllAster[AsterIndex]->MCUpdateEvent();TArray<FStardustBasic>LostStardust;//统计因终点库存已满而丢包的星尘for(const auto&it:PackgeInfo.Stardusts){if(it.Quantity){LostStardust.Add(FStardustBasic(it.StardustId,it.Quantity));UE_LOG(LogTemp,Error,TEXT("%d %s can't put in target aster"),it.Quantity,*it.StardustId.ToString());}}return true;}//弹出路径中队尾的元素PackgeInfo.ExpectedPath.Pop();//更新包裹的路径UpdatePathEvent(PackgeInfo.ExpectedPath);return false;
}

        我们使用时间轴和设置actor变换的方式来使包裹在场景中移动,也可以实现游戏暂停时停止移动和恢复移动

四、道路

1.道路的数据结构

        在本游戏中,玩家可以建造多种道路,每种道路有不同的传输速度,最大建造距离和消耗,首先是数据表格的数据结构,这里和DataTable的互动可以看开发日志2(独立游戏《星尘异变》UE5 C++程序开发日志2——实现一个存储物品数据的c++类-CSDN博客)

USTRUCT(BlueprintType)
struct FRoadDataTable:public FTableRowBase
{FRoadDataTable() = default;FRoadDataTable(const FString& RoadName, ERoadType RoadType, int TransferSpeed, double MaximumLength): RoadName(RoadName),RoadType(RoadType),TransferSpeed(TransferSpeed),MaximumLength(MaximumLength){}GENERATED_USTRUCT_BODY()//道路名称UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="RoadInfo")FString RoadName{"Empty"};//道路种类UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="RoadInfo")ERoadType RoadType{ERoadType::Empty};//传输速度,单位距离/秒UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="RoadInfo")int TransferSpeed{1};//最大长度UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="RoadInfo")double MaximumLength{1};//道路建造消耗UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="RoadInfo")TMap<FString,int>RoadConsumption;};

        然后是每条建造出来的道路的数据结构,包括道路的起点和终点,用的是所连建筑物的全局索引,以及这条路建成的长度和表格数据。我们有一个数组维护着所有场上的建筑物的指针,通过这两个索引就可以访问到道路两端的建筑

USTRUCT(BlueprintType)
struct FRoadInformation
{friend bool operator<(const FRoadInformation& Lhs, const FRoadInformation& RHS){return Lhs.distance > RHS.distance;}friend bool operator<=(const FRoadInformation& Lhs, const FRoadInformation& RHS){return !(RHS < Lhs);}friend bool operator>(const FRoadInformation& Lhs, const FRoadInformation& RHS){return RHS < Lhs;}friend bool operator>=(const FRoadInformation& Lhs, const FRoadInformation& RHS){return !(Lhs < RHS);}friend bool operator==(const FRoadInformation& Lhs, const FRoadInformation& RHS){return Lhs.TerminalIndex == RHS.TerminalIndex && Lhs.StartIndex==RHS.StartIndex;}friend bool operator!=(const FRoadInformation& Lhs, const FRoadInformation& RHS){return !(Lhs == RHS);}FRoadInformation() = default;explicit FRoadInformation(const int& StartIndex,const int& TerminalIndex,const FVector&StartLocation,const FVector&EndLocation,const FRoadDataTable& Road):StartIndex(StartIndex), TerminalIndex(TerminalIndex),distance(StartLocation.Distance(StartLocation,EndLocation)),RoadInfo(Road){}GENERATED_USTRUCT_BODY()UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Road")int StartIndex{0};//起点天体的索引UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Road")int TerminalIndex{0};//终点天体的索引UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Road")int distance{0};//两个天体之间的距离,取整//道路的数据UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Road")FRoadDataTable RoadInfo;};

2.道路的建造

        我们用一个红黑树来储存每个建筑都分别链接了哪些建筑

	std::map<int,TArray<TSharedPtr<FRoadInformation>>> AsterGraph;//所有天体构成的图

        在建造道路时传入起点和终点索引,以及道路类型的名称,将建造的道路存入上面存图的容器中

bool ATradingSystemActor::RoadBuilt(const int& Aster1, const int& Aster2,const FString& RoadName)
{if(!DebugActor->IsValidLowLevel()){UE_LOG(LogTemp,Error,TEXT("RoadBuild failed,invalid pointer:DebugActor"));return false;}//这两个建筑之间已存在道路,不可重复建造if(AsterGraph[Aster1].FindByPredicate([Aster2](const TSharedPtr<FRoadInformation>& Road){return Road->TerminalIndex==Aster2;})){return false;}//对应索引的天体不存在if(!DebugActor->AllAster.Find(Aster1)||!DebugActor->AllAster.Find(Aster2)){UE_LOG(LogTemp,Error,TEXT("RoadBuilt failed,invalid index :%d %d"),Aster1,Aster2);return false;}//数据表中存储的道路信息auto RoadInfo{*Instance->RoadDataMap[TCHAR_TO_UTF8(*RoadName)]};//存双向边AsterGraph[Aster1].Add(MakeShared<FRoadInformation>(Aster1,Aster2,DebugActor->AllAster[Aster1]->AsterPosition,DebugActor->AllAster[Aster2]->AsterPosition,RoadInfo));AsterGraph[Aster2].Add(MakeShared<FRoadInformation>(Aster2,Aster1,DebugActor->AllAster[Aster2]->AsterPosition,DebugActor->AllAster[Aster1]->AsterPosition,RoadInfo));return true;
}

3.道路的销毁

        在销毁道路时,我们需要将存的图中的该道路删除,同时对于所有传输中的包裹,如果其原本的路径中包含这条道路,则重新计算路径,如果计算路径失败则将包裹送到下一个到达的建筑物处

void ATradingSystemActor::RoadDestructed(const int& Aster1, const int& Aster2)
{if(!DebugActor->IsValidLowLevel()){UE_LOG(LogTemp,Error,TEXT("RoadDestructed failed,invalid pointer:DebugActor"));return;}//两个方向都要删除AsterGraph[Aster1].RemoveAll([Aster2](const TSharedPtr<FRoadInformation>& Road){return Road->TerminalIndex==Aster2;});AsterGraph[Aster2].RemoveAll([Aster1](const TSharedPtr<FRoadInformation>& Road){return Road->TerminalIndex==Aster1;});//遍历所有在路上的包裹for(auto&it:TransferingPackage){auto Temp{it->GetPackageInfo()};//遍历其计划经过的天体for(int i=Temp.ExpectedPath.Num()-1;i>=1;i--){//是否经过该条道路if(Temp.ExpectedPath[i]==Aster1&&Temp.ExpectedPath[i-1]==Aster2||Temp.ExpectedPath[i]==Aster2&&Temp.ExpectedPath[i-1]==Aster1){//尝试重新计算路径auto TempArray{ReRoute(Temp.ExpectedPath[Temp.ExpectedPath.Num()-1],Temp.ExpectedPath[0])};//没有能到终点的道路了if(TempArray.IsEmpty()){UE_LOG(LogTemp,Error,TEXT("RerouteFailed"));//将终点改为下一个天体TArray<int>Result;Result.Add(Temp.ExpectedPath[Temp.ExpectedPath.Num()-1]);Temp.ExpectedPath=Result;it->SetPackageInfo(Temp);it->UpdatePathEvent(Temp.ExpectedPath);break;}//应用新的路径Temp.ExpectedPath=TempArray;it->SetPackageInfo(Temp);it->UpdatePathEvent(Temp.ExpectedPath);break;}}}
}

4.某个有道路连接的建筑被删除

        在有道路连接的建筑被删除后,所有路径中包含该建筑的包裹要重新寻路,如果不能到达终点,同样送到下一个建筑为止

void ABP_Asters::AsterDestructed()
{ //这里展示的仅是该函数中关于物流系统的部分//删除以该天体为起点的道路TradingSystem->AsterGraph.erase(AsterIndex);for(auto&it:TradingSystem->AsterGraph){//删除以该天体为终点的道路auto temp{AsterIndex};it.second.RemoveAll([temp](const TSharedPtr<FRoadInformation>& Road){return Road->TerminalIndex==temp;});}for(int i=0;i<TradingSystem->TransferingPackage.Num();i++){auto it{TradingSystem->TransferingPackage[i]};if(!IsValid(it)){TradingSystem->TransferingPackage.RemoveAt(i);i--;continue;}auto Temp{it->GetPackageInfo()};bool NeedReroute{false};//计划路径中有该天体就需要重新寻路for(auto& it2:Temp.ExpectedPath){if(it2==AsterIndex){NeedReroute=true;}}if(NeedReroute){        //下一个目的地就是该天体,直接删除if(Temp.ExpectedPath.Num()==1){it->Destroy();continue;}//终点是该天体,那肯定找不到路了if(Temp.ExpectedPath[0]==AsterIndex){UE_LOG(LogTemp,Error,TEXT("Reroute failed"));TArray<int>Result;Result.Add(Temp.ExpectedPath[Temp.ExpectedPath.Num()-1]);Temp.ExpectedPath=Result;it->SetPackageInfo(Temp);it->UpdatePathEvent(Temp.ExpectedPath);continue;}//尝试重新寻路auto TempArray{TradingSystem->ReRoute(Temp.ExpectedPath[Temp.ExpectedPath.Num()-1],Temp.ExpectedPath[0])};//没找到合适的道路if(TempArray.IsEmpty()){UE_LOG(LogTemp,Error,TEXT("Reroute failed"));TArray<int>Result;Result.Add(Temp.ExpectedPath[Temp.ExpectedPath.Num()-1]);Temp.ExpectedPath=Result;it->SetPackageInfo(Temp);it->UpdatePathEvent(Temp.ExpectedPath);continue;}//应用新的路径Temp.ExpectedPath=TempArray;it->SetPackageInfo(Temp);it->UpdatePathEvent(Temp.ExpectedPath);}}//蓝图实现的事件,因为道路的指针存在蓝图里,所以交给蓝图来删除对象AsterDestructedEvent(this);
}


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3250334.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Apache SeaTunnel——OLAP 引擎的数据动脉

导读本文将分享如何利用 Apache SeaTunnel 将各个业务系统的数据同步到 OLAP 引擎。 主要内容包括以下六大部分&#xff1a; 1. Apache SeaTunnel 项目介绍 2. Apache SeaTunnel 核心功能 3.SeaTunnel 在 OLAP 场景下的应用 4. 社区近期计划 5. WhaleTunnel 产品特性 6. …

《Winodws API每日一练》11.3 工具栏控件

本节将讲述工具栏控件的创建和使用。 本节必须掌握的知识点&#xff1a; 工具栏控件 第72练&#xff1a;工具栏控件 11.3.1 工具栏控件 工具栏控件&#xff08;Toolbar Control&#xff09;是Windows操作系统提供的一种用户界面元素&#xff0c;用于显示常用的命令按钮、工具…

PostgreSQL创建表和自增序列

一、创建表&#xff1a; 注意&#xff1a; 1、在mysql没有序列的概念&#xff0c;id自增通过auto_increment实现&#xff1b; 2、pgsql没有auto_increment的概念&#xff0c;如何实现id自增&#xff1f;有两种方式&#xff1a; 方式一&#xff1a;创建序列&#xff0c;绑定…

MYSQL调优详解:案例解析(第40天)

系列文章目录 一、数据库设计优化 二、查询优化 三、架构优化 四、其他优化策略 五、优化案例解析 文章目录 系列文章目录前言一、数据库设计优化二、查询优化三、架构优化四、其他优化策略五、优化案例解析案例一&#xff1a;优化SELECT查询案例二&#xff1a;使用索引案例三…

springboot系列十: 自定义转换器,处理JSON,内容协商

文章目录 自定义转换器基本介绍应用实例查看源码注意事项和细节 处理JSON需求说明应用实例 内容协商基本介绍应用实例debug源码优先返回xml注意事项和细节 ⬅️ 上一篇: springboot系列九: 接收参数相关注解 &#x1f389; 欢迎来到 springboot系列十: 自定义转换器&#xff0c…

ELK日志收集

一、什么是ELK ELK 是由 Elasticsearch、Logstash、Kibana 三个开源软件的组成的一个组合体&#xff0c;ELK 是 elastic 公司研发的一套完整的日志收集、分析和展示的企业级解决方案。 ELK 的好处&#xff1a; ELK 组件在大数据运维系统中&#xff0c;主要可解决的问题如下&…

MDK5没有DeviceName

遇到的问题是Jlink驱动问题 不是引脚接反 使用国产GD单片机不同的工程&#xff0c;有的有Device Name,有的没有Device Name&#xff08;下图是弄好的情况&#xff0c;有Device Name&#xff09; 硬件链接&#xff0c;和设备都没有问题&#xff1a;无法仿真&#xff0c;无法下…

ARM体系结构和接口技术(四)LED灯实验---②

文章目录 一、特殊功能控制寄存器&#xff08;一&#xff09;GPIOx_MODER寄存器&#xff08;二&#xff09;GPIOx_OTYPER寄存器&#xff08;三&#xff09;GPIOx_OSPEEDR寄存器&#xff08;四&#xff09;GPIOx_PUPDR寄存器&#xff08;五&#xff09;GPIOx_IDR寄存器&#xff…

C语言——详解二级指针及其与二维数组的误区、指针定义大全

C语言中的二级指针&#xff08;也称为指针的指针&#xff09;是指一个指针变量&#xff0c;它存储的不是普通的值&#xff0c;而是另一个指针的地址。这意味着你可以通过二级指针来访问和修改另一个指针的值。这种结构在C语言中非常有用&#xff0c;尤其是在处理动态内存分配、…

C语言实现二叉树以及二叉树的详细介绍

目录 1.树概念及结构 1.1树的概念 1.2树的相关概念 1.3树的表示 2.二叉树概念及结构 2.1二叉树的概念 2.2特殊的二叉树 2.3二叉树的性质 2.4二叉树的存储结构 3.二叉树顺序结构--特殊的二叉树--堆及其实现 3.1堆的概念及结构 3.2堆的实现 3.2.1堆的结构 3.2.2堆…

《昇思25天学习打卡营第25天|第22天》

今天是学习的第22天&#xff0c;今天学的是应用实践的自然语言处理的RNN实现情感分类。 从情感分类开始学习&#xff0c;数据准备、数据下载模块、加载IMDB数据集、加载预训练词向量、数据集预处理、模型构建、Embedding、RNN(循环神经网络)、Dense、损失函数与优化器、训练逻…

Github狂揽2.8k stars,可一键生成绘画全过程,却引发全球骂战

大家好&#xff0c;我是程序员X小鹿&#xff0c;前互联网大厂程序员&#xff0c;自由职业2年&#xff0c;也一名 AIGC 爱好者&#xff0c;持续分享更多前沿的「AI 工具」和「AI副业玩法」&#xff0c;欢迎一起交流~ 这项 AI 技术刚一上线&#xff0c;就在 Github 狂揽 1k stars…

数据库理论基础

1.什么是数据库 1.1数据 描述事物的符号记录&#xff0c; 可以是数字、 文字、图形、图像、声音、语言等&#xff0c;数据有多种形式&#xff0c;它们都可以经过数字化后存入计算机。 1.2数据库 存储数据的仓库&#xff0c;是长期存放在计算机内、有组织、可共享的大量数据…

C++初学者指南-5.标准库(第一部分)--标准库最小/最大算法

C初学者指南-5.标准库(第一部分)–标准库min/max算法 文章目录 C初学者指南-5.标准库(第一部分)--标准库min/max算法minmaxminmaxclamp (C17)min_elementmax_elementminmax_element相关内容 C标准库算法是一块新领域&#xff1f;⇒简短介绍 min min(a, b) → a 如果 a < b则…

全国产服务器主板:搭载飞腾FT2000+/64处理器的高性能加固服务器

近期很多朋友咨询全国产化的服务器主板。搭载的是飞腾FT-2000/64的全国产化服务器主板。他的主要特点是&#xff1a;①丰富的PCIe、千兆以太网、SATA接口&#xff0c;可用作数据处理、存储、通信服务器&#xff1b;②​​​​​​​板载独立显示芯片&#xff0c;对外HDMI/VGA/L…

C语言第5天作业 7月16日

目录 1.求1000以内所有的质数。 2.有1、2、3、4个数字&#xff0c;能组成多少个互不相同且无重复数字的三位数&#xff1f;都是多少&#xff1f; 3.猴子吃桃问题 4.判断最大值 1.求1000以内所有的质数。 质数&#xff1a;只能够1和它本身整除 #include <stdio.h> in…

Java 快速入门学习 -- Day 2

Java 快速入门 Ⅱ 学习视频maven&#xff08;图书管理员&#xff09;IDEA使用 maven框架MyBatis① MyBatis 是持久层框架② MyBatis 是 ORM 框架③ 搭建第一个 MyBatis 框架1、创建数据库表&#xff08;wy数据库 t_book 表&#xff09;2、创建maven 项目3、添加依赖4、创建 My…

万界星空科技MES系统生产计划管理的功能

MES系统&#xff08;Manufacturing Execution System&#xff0c;制造执行系统&#xff09;的生产计划管理功能是其核心功能之一&#xff0c;旨在将企业的生产计划转化为实际的生产操作&#xff0c;并通过实时监控和调整来确保生产活动的顺利进行。以下是MES系统生产计划管理功…

关于 Qt输入法在arm特定的某些weston下出现调用崩溃 的解决方法

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/140423667 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

算法篇 滑动窗口 leetCode 水果成篮

水果成蓝 1.题目描述2.图形分析2.1原理解释2.2 怎么想出使用滑动窗口2.3 图形分析 3.代码演示 1.题目描述 2.图形分析 2.1原理解释 2.2 怎么想出使用滑动窗口 2.3 图形分析 3.代码演示