D9D10决赛信息交互+分组文件读入

书接上回,记得昨天留下的问题吗。

1.通过字符串来实现不同的纹理绑定。

2.字符串的转换

突破1

然后今天我发现,其实用不上什么mes、message来调控,我们不是已经有了一个条件了吗:

if ((camera.m_Position.x <= (outlinePos[i - 1].x + 0.2f) && camera.m_Position.x >= (outlinePos[i - 1].x - 0.2f)) && (camera.m_Position.y <= (outlinePos[i - 1].y + 0.2f) && camera.m_Position.y >= (outlinePos[i - 1].y - 0.2f))) 

如果判断成功,不就意味着我们轮廓已经绘制,岂不是可以直接绑定纹理?不在需要其他条件控制,不需要获取什么mes。

突破2

昨天一直在考虑怎样将已获取的字符串转换为一个texture类型的变量,然后使用其成员函数Bind(),后来发现其实Bind()中不过两行代码,直接在主函数中硬编码实现即可,这下也不用考虑什么静态函数之类的问题了。

突破3

因为之前绑定过两个纹理,所以在内存中前两个的m_RenderID分别是unsigned int 的0和1,想要绑定之后的12个纹理,需要GLCALL(glBindTexture(GL_TEXTURE_2D, i + 3)),然后,然后又发现一个问题

突破4

for(size_t i = 1; i < outlinePos.size() + 1; i++){

记得之前的i吗,现在我们没必要让i从1开始,可以让他为0开始.

做总结

//绘制outlining
GLCALL(glStencilMask(0x00));																				//禁止模板写入
GLCALL(glStencilFunc(GL_NOTEQUAL, 1, 0xff));																//模板值不等于缓冲区中模板值时更新 通过测试
glDisable(GL_DEPTH_TEST);																					//选中的物体可以透过遮挡,不使用深度测试
outlineShader.Bind();
outlineShader.SetUniformMatrix4fv("u_Projection", projection.GetMatrixData());
outlineShader.SetUniformMatrix4fv("u_View", view.GetMatrixData());
for(size_t i = 0; i < outlinePos.size(); i++){
    if ((camera.m_Position.x <= (outlinePos[i].x + 0.2f) && camera.m_Position.x >= (outlinePos[i].x - 0.2f)) && (camera.m_Position.y <= (outlinePos[i].y + 0.2f) && camera.m_Position.y >= (outlinePos[i].y - 0.2f)))
    {
        Matrix stencilModel("mat4");
        stencilModel.Rotate(90.0f, glm::vec3(1.0f, 0.0f, 0.0f));
        stencilModel.Translate(labels[i]);
        stencilModel.Scale(glm::vec3(1.5f, 1.5f, 1.5f));
        outlineShader.SetUniformMatrix4fv("u_Model", stencilModel.GetMatrixData());
        renderer.DrawElements(cuboidVa, cuboidIb, outlineShader);
        //messages
        GLCALL(glDisable(GL_DEPTH_TEST));
        GLCALL(glViewport(SCR_WIDTH / 3, SCR_WIDTH / 2.5, SCR_WIDTH / 2.5, SCR_HEIGHT / 2.5));
        quadShader.Bind();
        GLCALL(glActiveTexture(GL_TEXTURE0));
        GLCALL(glBindTexture(GL_TEXTURE_2D, i + 3   ));
        renderer.DrawArrays(quadVa, 6, quadShader);
        GLCALL(glBindTexture(GL_TEXTURE_2D, 0));
    }
}
glEnable(GL_DEPTH_TEST);																					//恢复深度测试
GLCALL(glStencilMask(0xFF));

开始做条件2吧

等不及了

之前我们实现了imgui的窗口和button,现在我们需要添加一些条件语句和作用域更改。

e99d0b7910314adfb023a9d53b5affa6.png

 记得之前的代码吗,我先在文本渲染中打印一下当前时间

#define _CRT_SECURE_NO_WARNINGS //在现在版本c++标准库中使用localtime函数会出现警告,在确保安全的情况系故禁用这个警告
#include<sstream>
#include<ctime>
#include<cmath>
#include<chrono>
#include<iomanip>
std::string GetTime()
{
	auto now = std::chrono::system_clock::now();			// 获取当前时间点  
	auto timestamp = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count(); // 将时间点转换为时间戳(以秒为单位)  
	std::time_t time_from_epoch = std::time_t(timestamp);	// 转换为time_t类型,以便能够使用ctime函数进行格式化输出  
	std::tm local_time = *std::localtime(&time_from_epoch); // 转换为本地时间并格式化输出  
	std::ostringstream oss;									// 使用ostringstream构建字符串  
	oss << std::put_time(&local_time, "%Y-%m-%d %H:%M:%S"); // 将本地时间格式化为字符串  
	return oss.str();										// 将字符串存储在std::string变量中  
}

 设置了一个表示时间的函数,然后在application中

std::string time = GetTime();
if (fontDraw) {
                //....
                font.RenderText(fontShader, time, 25.0f, 25.0f, 1.0f, glm::vec3(0.5, 0.8f, 0.2f));
            }

a5bfe261e5634d2d9280053554e43dfe.png

and we got it ! (左下角)

f277898917bc45dda910c29643d836e6.png

而且单击exit按钮,我们也可以退出这个打印。

接下来的任务

现在我们需要做的是,通过初赛成绩进行决赛分组,生成一个秩序册,将队伍分配到17个决赛室(秩序册中每个决赛室的进场顺序为初赛成绩降序排列)。然后模拟候赛区大屏上动态展示各参赛队候场、比赛中、比赛结束的状态。

所以为了渲染比赛状态,我需要先对进行初赛的队伍分组,生成秩序册之后从中读取文字,用来显示在大屏上。

---------------------------------------------------------------------------------------------------------------------

在阅读任务书后发现,team.txt文件和有决赛室标识的文件其实很相像,分给这些队伍60~100的成绩就是默认了他们都进入决赛,所以我可以给team.txt分一些初赛成绩,然后以有决赛室标识的这个文件为条件后面再去判断。

我觉得是可以先写一个脚本,读入team.txt文件,然后依次为每一行队伍分配一个60到100的初赛成绩,读出并保存,然后去使用这个更新后的文件(反正也不影响条件一那些增删查的问题)。让我们开始吧。

初赛成绩赋值脚本

2530f27936d0458a8d89ae9d2d899637.png

#include <iostream>  
#include <fstream>  
#include <sstream>  
#include <string>  
#include <random>  

int main() {  
	const std::string& inputPath = "YOUR LOCAL FILEPATH"; // 替换为你的输入文件路径  
    const std::string& outputPath = "WRITE IN THIS FILE"; // 替换为你的输出文件路径  
    std::ifstream inputStream(inputPath);  
    std::ofstream outputStream(outputPath);  
    std::string line;  
    if (!inputStream.is_open() || !outputStream.is_open()) {  
        std::cerr << "Failed to open the file." << std::endl;  
        return 1;  
    }  

    std::random_device rd;  
    std::mt19937 gen(rd());  
    std::uniform_int_distribution<> dis(60, 100); 				// 60到100之间的随机数  
    
    while (getline(inputStream, line)) {  
        if (!line.empty()) {                               		// 检查行是否为空,因为第一行可能是空的  
            std::uniform_int_distribution<> disNew(60, 100); // 生成一个新的随机数分布  
            int randomNum = disNew(gen);  					// 生成一个新的随机数并存储在变量中  
            line += "\t" + std::to_string(randomNum);  		// 在行末添加一个制表符和一个新的随机数  
            outputStream << line << std::endl; 				// 将修改后的行写入新的文件  
        } 
    }  
    inputStream.close();  
    outputStream.close();  
    return 0;  
}

然后我的到了一个有成绩的文件

cb5008d5a41a4ab7a3f3a38a0b2cdb68.png

虽然第一行多了个数字但无伤大雅。

记得我们说过team.txt和“决赛分组-江科大.txt”这个文件差不多吗,反正都是要用,不如直接用这个文件来添加随机数,等会判断决赛室时候也方便。

故对“决赛分组-江科大.txt”重命名,改成英文的,然后使用刚才那个脚本处理一下。

fb730e73c74c423898e8b49f281e14ab.png

( 偷偷删除第一行的那个数字:) )

那么我们就处理好了,接下来就是写一个代码来按照每一个决赛室中的队伍和初赛成绩来分类。(要不也写一个脚本处理?)

决赛分组

排序方式用归并排序或直接插入排序,因为稳定。然后归并开销较小,但直接插入易编码实现。各有裨益。

所以我又写了一个脚本。

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <random>
#include <vector>
#include <algorithm>  		//sort函数

int main() {
    const std::string& inputPath = "刚才得到的输出的文件";
    const std::string& outputPath = "输出目标文件";
    
    std::ifstream inputStream(inputPath);
    std::ofstream outputStream(outputPath);
    std::string line;

    if (!inputStream.is_open() || !outputStream.is_open()) {
        std::cerr << "Failed to open the file." << std::endl;
        return 1;
    }
    
    std::vector<std::pair<std::string, int>> DataWithScores;
    while (getline(inputStream, line)) {
        if (!line.empty()) { 											// 检查行是否为空,因为第一行可能是空的
            if (line[0] == '1' && line[1] == '\t') { 			// 从一行数据头部开始到第二个字符,查找'1'
                int length = line.length();
                std::string score = line.substr(length - 3, 3); // 获取这一行的最后两个元素,假设这是成绩
                int num = std::stoi(score);
                DataWithScores.push_back(std::make_pair(line, num)); 	// 将行和成绩存储在容器中
            }
            else{
            	std::cout << "fa la la";
			}
        }
    }
    inputStream.close();
    
    std::sort(DataWithScores.begin(), DataWithScores.end(), [](const std::pair<std::string, int>& a, const std::pair<std::string, int>& b) {
        return a.second > b.second;										// 根据成绩降序排序 (到时候改成直接插入排序,排的是pair存储的分数num)
    });

    for (const auto& pair : DataWithScores) {  
        outputStream << pair.first << std::endl;					 	// 将排序后的行写入到输出文件  
    }
    outputStream.close();
    
    return 0;
}

现在我们对决赛组为1的队伍们进行了成绩的降序排序。

这是上一次处理的带随机分数的数据。

7aed98745fd049719f708e183143ed23.png

 这是按照成绩排序的分组。(上面的脚本额只写了决赛组为1的降序排序)

f61ff0874704467882eb273f7337bd5c.png

处理的关键代码是

while (getline(inputStream, line)) {
        if (!line.empty()) { 											// 检查行是否为空,因为第一行可能是空的
            if (line[0] == '1' && line[1] == '\t') { 			// 从一行数据头部开始到第二个字符,查找'1'
                int length = line.length();
                std::string score = line.substr(length - 3, 3); // 获取这一行的最后两个元素,假设这是成绩
                int num = std::stoi(score);
                DataWithScores.push_back(std::make_pair(line, num)); 	// 将行和成绩存储在容器中
            }
			

        }
    }

之后呢就是if (line[0] == '  2或3或4...直到9  ' && line[1] == '\t'),因为line[0]只有一个字符嘛,

后面要改为if (line[0] == '1' && line[2] == '  1或2或3...直到7  ' && line[3] == '\t')这样就好

757eb91b0cdf4efeba63487e833c01fc.png

最后我们得到了这样的文件。

---------------------------------------------------------------

明天将使用这样的文件,来进行赛场信息打印。同时更改排序方式为简单选择排序。

  • 19
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先使用 lsblk 命令查看当前系统的磁盘信息: ``` $ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 477G 0 disk ├─sda1 8:1 0 1G 0 part /boot ├─sda2 8:2 0 8G 0 part [SWAP] └─sda3 8:3 0 468G 0 part / sdb 8:16 0 20G 0 disk ├─sdb1 8:17 0 1G 0 part /mnt/usb └─sdb2 8:18 0 19G 0 part /mnt/data sr0 11:0 1 1024M 0 rom ``` 可以看到,当前系统中有两个硬盘 sda 和 sdb,以及一个光驱设备 sr0。其中,sda 分为三个分区,分别是 /boot、SWAP 和 /,sdb 分为两个分区,分别是 /mnt/usb 和 /mnt/data。 接下来,如果想观查磁盘映像文件信息,可以使用以下命令: ``` $ lsblk -f NAME FSTYPE LABEL UUID FSAVAIL FSUSE% MOUNTPOINT sda ├─sda1 ext4 boot 8d2c12cc-5a94-47d9-9cb8-3a3f1f5c5d5d 63.5M 17% /boot ├─sda2 swap 7a5a5d2a-83d8-4ca2-9e10-9b1d8b17a3b3 └─sda3 ext4 root 0f3645e5-5e9c-4f1d-b7f1-5ca5aeb2c8be 281.1G 13% / sdb ├─sdb1 vfat USB_DRIVE 7C4D-1E3D /mnt/usb └─sdb2 ext4 data 94e15678-7c92-4d31-9aa3-3e1b9d9e8a3c 2.2G 1% /mnt/data sr0 ``` 在 lsblk 命令后加上 -f 参数,可以查看磁盘分区的文件系统类型、标签和 UUID 等信息。可以看到,sdb1 分区的文件系统类型是 vfat,标签是 USB_DRIVE,UUID 是 7C4D-1E3D;sdb2 分区的文件系统类型是 ext4,标签是 data,UUID 是 94e15678-7c92-4d31-9aa3-3e1b9d9e8a3c。如果有磁盘映像文件的话,可以通过查看其文件系统类型和 UUID 等信息来确认它是否挂载成功。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值