在线刷题系统测试报告

news2024/10/23 1:54:12

一、项目背景

1. 本项目是一个在线刷题系统,灵感来源于力扣和牛客等刷题平台,旨在锻炼自己的代码能力和剖析系统整体结构与各模块之间关系的能力。系统支持用户注册与登录,查看题目列表与题目详情,在线提交代码并提供反馈。
2. 该系统采用前后端分离的方法来实现,同时使用了数据库来存储相关的数据,如题目数据,以及用户的相关信息。整个服务将被部署到 Linux 云服务器上。前端主要由六个页面构成:首页、注册页面、登录页面、题目列表页、题目详情页以及未完成模块的告知页面,以上就模拟实现了一个简单的在线刷题系统。
3. 该系统没有实现诸如竞赛、论坛这些功能,只提供了最基础的刷题以及判题服务,并且登录用户也无法自定义自己的头像。


二、项目功能

1. 注册功能:用户通过表单提交要注册的用户名以及密码,后端会构建 SQL 语句,在 MySQL 中进行数据插入操作,根据语句执行的成功与否来判断用户要注册的用户名是否存在冲突。注册成功后,会有弹窗提示用户,点击后将跳转到登录页面,方便用户进行登录。注册失败则会弹窗提示用户名已经被使用。
2. 登录功能:用户通过表单提交要登录的用户名以及密码,后端会构建 SQL 语句,在 MySQL 中进行数据查询操作,首先判断有没有对应的用户信息,然后将用户提交的密码进行哈希,并与MySQL 中存储的密码哈希值进行比对,如果相同则登录成功,成功登录后同样会有弹窗提示用户,点击后会跳转到首页。登录失败则会弹窗提升用户名或密码错误。在登录状态下,用户访问的每个页面都会发生变化,右上角不再显示注册于登录按钮,取而代之的是用户头像以及注销按钮。
3. 题目列表:用户可以在题目列表页面查看当前系统提供的所有题目,每道题目都有它的标号、标题以及难度,用户可以点击具体的一道题目,然后会跳转到这道题目的详情页。
4. 题目详情:该页面会显示题目的具体描述、要求、示例、提示信息以及代码编辑框,用户可以在该页面进行代码的编写,编写完毕后,可以点击右下角的提交代码按钮,就会将代码提交给后端服务器进行编译并运行,并将结果在下方的输出框中显示。


三、项目测试

(一)功能测试

        1. 首先通过 Xmind 软件来编写功能测试用例:

        2. 打开浏览器,在网址栏中输入在线刷题服务的 url,手动进行上述测试。

        (1)正常登录。

        (2)异常登录。

        (3)正常注册。

        (4)异常注册。

        (5)正常注销。

 

        (6)查看题目列表页,并测试点击具体题目后能否跳转到题目详情。

 

        (7)不编写代码直接提交。

        (8)编写语法错误代码并提交。

        (9)编写语法正确,但解题错误的代码提交。

        (10)编写语法正确,解题也正确的代码提交。


(二)自动化测试

        1. 编写自动化测试用例。

        2. 使用 Python 编写自动化测试脚本。

        (1)通用模块的编写

import datetime
import os.path
import sys

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.wait import WebDriverWait
from webdriver_manager.chrome import ChromeDriverManager

class Driver:
    driver = ""

    def __init__(self):
        options = webdriver.ChromeOptions()
        self.driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)

    def screenShot(self):
        dirName = datetime.datetime.now().strftime("%Y-%m-%d")
        if not os.path.exists("../images/" + dirName):
            os.mkdir("../images/" + dirName)

        filename = sys._getframe().f_back.f_code.co_name + "-" + datetime.datetime.now().strftime("%H%M%S") + ".png"
        self.driver.save_screenshot("../images/" + dirName + "/" + filename)


ojDriver = Driver()
wait = WebDriverWait(ojDriver.driver, 2)

因为所有页面的测试都需要用到 driver 对象,因此先提前创建好,让所有测试模块共用同一个 driver 对象。
并且有时候需要屏幕截图来判断当前页面是否存在什么问题,因此添加一个屏幕截图方法,采用调用该方法时的日期来充当图片文件所在的目录,而图片文件的名字则由调用屏幕截图时所在的方法名以及当时的时间构成。
最后再创建一个 wait 对象用于显示等待。

        (2)注销功能的测试用例编写

from common.Utils import wait
from common.Utils import ojDriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

class Logout:
    url = "http://121.37.30.235:8888/"
    driver = ojDriver.driver
    LOGOUT_BUTTON_SELECTOR = "body > div.navbar > div.profile-section > a"
    WELCOME_MESSAGE_SELECTOR = "body > div.content > h1"

    def __init__(self):
        self.driver.get(self.url)

    def logout(self, check = False):
        wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, self.LOGOUT_BUTTON_SELECTOR))).click()
        if check:
            text = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, self.WELCOME_MESSAGE_SELECTOR))).text
            assert text == "欢迎来到我的在线编程平台"
            ojDriver.screenShot()

先访问网站首页,然后尝试定位页面上的注销按钮,这个过程添加了显示等待,防止因为页面还没完全加载而导致元素定位失败而报错,毕竟代码执行的速度太快了。
定位到之后就点击注销,此时页面会跳转到首页,并且首页中心的文字也会发生改变,此时根据参数来决定是否要对该功能进行检查,因为后续登录测试要频繁用到注销功能,因此不是每一次调用都需要去生成截图文件。

        (3)登录页面的测试用例编写

from common.Utils import wait
from common.Utils import ojDriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

class Login:
    url = "http://121.37.30.235:8888/login.html"
    driver = ojDriver.driver
    USERNAME_INPUT_SELECTOR = "body > div > div > form > input[type=text]:nth-child(1)"
    PASSWORD_INPUT_SELECTOR = "body > div > div > form > input[type=password]:nth-child(2)"
    LOGIN_BUTTON_SELECTOR = "body > div > div > form > input[type=submit]:nth-child(3)"
    WELCOME_MESSAGE_SELECTOR = "body > div.content > h1"

    def __init__(self):
        self.driver.get(self.url)

    def loginSuccess(self, username, password, check = False):
        ele1 = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, self.USERNAME_INPUT_SELECTOR)))
        ele2 = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, self.PASSWORD_INPUT_SELECTOR)))
        ele1.clear()
        ele2.clear()
        ele1.send_keys(username)
        ele2.send_keys(password)
        wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, self.LOGIN_BUTTON_SELECTOR))).click()

        wait.until(EC.alert_is_present())
        alert = self.driver.switch_to.alert
        assert alert.text == "登录成功,将跳转至首页"
        alert.accept()

        if check:
            text = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, self.WELCOME_MESSAGE_SELECTOR))).text
            assert text == f"欢迎回来,{username}!"
            ojDriver.screenShot()

    def loginFail(self, username, password, check = False):
        ele1 = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, self.USERNAME_INPUT_SELECTOR)))
        ele2 = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, self.PASSWORD_INPUT_SELECTOR)))
        ele1.clear()
        ele2.clear()
        ele1.send_keys(username)
        ele2.send_keys(password)
        wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, self.LOGIN_BUTTON_SELECTOR))).click()

        # 当有弹窗出现时,必须先处理该弹窗,然后才能截图,不然会报错
        wait.until(EC.alert_is_present())
        alert = self.driver.switch_to.alert
        assert alert.text == "登录失败,请检查您的用户名和密码"
        alert.accept()

        if check:
            assert self.driver.current_url == "http://121.37.30.235:8888/login.html"
            ojDriver.screenShot()

登录测试中需要分别测试正常登录与异常登录,它们分别为两个方法。这里通过弹窗的文字来判断是否登陆成功,处理了弹窗后会有页面的跳转,如果要截图的话,则可以在这时候截图。

        (4)注册页面的测试用例编写

from common.Utils import wait
from common.Utils import ojDriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

class Register:
    url = "http://121.37.30.235:8888/register.html"
    driver = ojDriver.driver
    USERNAME_INPUT_SELECTOR = "body > div > div > form > input[type=text]:nth-child(1)"
    PASSWORD_INPUT_SELECTOR = "body > div > div > form > input[type=password]:nth-child(2)"
    CONFIRM_INPUT_SELECTOR = "body > div > div > form > input[type=password]:nth-child(3)"
    REGISTER_BUTTON_SELECTOR = "body > div > div > form > input[type=submit]:nth-child(4)"

    def __init__(self):
        self.driver.get(self.url)

    def registerSuccess(self, username, password, check = False):
        ele1 = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, self.USERNAME_INPUT_SELECTOR)))
        ele2 = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, self.PASSWORD_INPUT_SELECTOR)))
        ele3 = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, self.CONFIRM_INPUT_SELECTOR)))
        ele1.clear()
        ele2.clear()
        ele3.clear()
        ele1.send_keys(username)
        ele2.send_keys(password)
        ele3.send_keys(password)
        wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, self.REGISTER_BUTTON_SELECTOR))).click()

        wait.until(EC.alert_is_present())
        alert = self.driver.switch_to.alert
        assert alert.text == "注册成功,将跳转至登录页面"
        alert.accept()

        if check:
            assert self.driver.current_url == "http://121.37.30.235:8888/login.html"
            ojDriver.screenShot()

    def registerFail(self, username, password, check = False):
        ele1 = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, self.USERNAME_INPUT_SELECTOR)))
        ele2 = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, self.PASSWORD_INPUT_SELECTOR)))
        ele3 = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, self.CONFIRM_INPUT_SELECTOR)))
        ele1.clear()
        ele2.clear()
        ele3.clear()
        ele1.send_keys(username)
        ele2.send_keys(password)
        ele3.send_keys(password)
        wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, self.REGISTER_BUTTON_SELECTOR))).click()

        wait.until(EC.alert_is_present())
        alert = self.driver.switch_to.alert
        assert alert.text == "注册失败,该用户名已存在"
        alert.accept()

        if check:
            assert self.driver.current_url == "http://121.37.30.235:8888/register.html"
            ojDriver.screenShot()

跟登录页面的测试用例差不多,只是注册时需要确认密码,因此要多定位一个输入框。

        (5)首页的测试用例编写

from common.Utils import wait
from common.Utils import ojDriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

class Index:
    url = "http://121.37.30.235:8888/"
    driver = ojDriver.driver
    LOGIN_BUTTON_SELECTOR = "body > div.navbar > div.auth-links > a.login"
    REGISTER_BUTTON_SELECTOR = "body > div.navbar > div.auth-links > a.register"
    PROFILE_PHOTO = "body > div.navbar > div.profile-section > div > img"
    LOGOUT_BUTTON_SELECTOR = "body > div.navbar > div.profile-section > a"

    def __init__(self):
        self.driver.get(self.url)

    def notLogin(self, check = False):
        ele1 = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, self.LOGIN_BUTTON_SELECTOR)))
        ele2 = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, self.REGISTER_BUTTON_SELECTOR)))
        assert ele1.text == "登录"
        assert ele2.text == "注册"

        if check:
            ojDriver.screenShot()

    def alreadyLogin(self, check = False):
        wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, self.PROFILE_PHOTO))).click()
        self.driver.back()

        if check:
            ojDriver.screenShot()

        ele1 = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, self.LOGOUT_BUTTON_SELECTOR)))
        assert ele1.text == "注销"
        ele1.click()

首页主要是针对登录状态与未登录状态的不同地方来进行测试,顺便截张图看看整体的页面效果。

        (6)题目列表页的测试用例编写

from common.Utils import wait
from common.Utils import ojDriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

class Questions:
    url = "http://121.37.30.235:8888/all_questions"
    driver = ojDriver.driver
    BIG_TITLE_SELECTOR = "body > div.question_list > h1"
    ID_SELECTOR = "body > div.question_list > table > tbody > tr:nth-child(1) > th:nth-child(1)"
    SMALL_TITLE_SELECTOR = "body > div.question_list > table > tbody > tr:nth-child(1) > th:nth-child(2)"
    DIFFICULTY_SELECTOR = "body > div.question_list > table > tbody > tr:nth-child(1) > th:nth-child(3)"
    QUESTION_SELECTOR = "body > div.question_list > table > tbody > tr:nth-child(7) > td:nth-child(2) > a"

    def __init__(self):
        self.driver.get(self.url)

    def showQuestions(self, check = False):
        ele1 = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, self.BIG_TITLE_SELECTOR)))
        ele2 = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, self.ID_SELECTOR)))
        ele3 = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, self.SMALL_TITLE_SELECTOR)))
        ele4 = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, self.DIFFICULTY_SELECTOR)))
        assert ele1.text == "题目列表"
        assert ele2.text == "编号"
        assert ele3.text == "标题"
        assert ele4.text == "难度"

        if check:
            ojDriver.screenShot()

        ele5 = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, self.QUESTION_SELECTOR)))
        assert ele5.text == "正则表达式匹配"

        if check:
            ele5.click()
            wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "body > div.part1 > div.right_code > button")))
            ojDriver.screenShot()

主要针对页面的元素进行定位,查看一下它的文本信息。然后测试点击题目后能否跳转到具体的题目详情页面。这里如果要截图的话,依旧要添加显示等待,等到题目详情页加载好后再去截图,否则截到的图会是没跳转之前的。

        (7)题目详情页的测试用例编写

from common.Utils import wait
from common.Utils import ojDriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

class Question:
    url = "http://121.37.30.235:8888/question/1"
    driver = ojDriver.driver
    ID_SELECTOR = "#id"
    DIFFICULTY_SELECTOR = "body > div.part1 > div.left_desc > h3 > small"
    SUBMIT_SELECTOR = "body > div.part1 > div.right_code > button"
    OUTPUT_SELECTOR = "body > div.part1 > div.right_code > div > p"

    def __init__(self):
        self.driver.get(self.url)

    def showQuestion(self, check = False):
        ele1 = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, self.ID_SELECTOR)))
        ele2 = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, self.DIFFICULTY_SELECTOR)))
        assert ele1.text == "1"
        assert ele2.text == "难度: 简单"

        ele3 = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, self.SUBMIT_SELECTOR)))
        assert ele3.text == "提交代码"
        ele3.click()
        ele3 = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, self.OUTPUT_SELECTOR)))
        assert ele3.text == "Segmentation fault"

        if check:
            ojDriver.screenShot()

同样针对页面上的一些元素去进行定位,查看它的文本信息显示的正不正常。然后点击提交按钮,此时由于什么代码也没写,输出框会报错:Segmentation fault。点击提交后,再截个图即可。

        (8)将所有测试用例运行起来

from test import Login
from test import Logout
from test import Register
from test import Index
from test import Questions
from test import Question
from common.Utils import ojDriver

if __name__ == "__main__":
    Login.Login().loginSuccess("admin", "123", True)
    Logout.Logout().logout(True)
    Login.Login().loginSuccess("张三", "123")
    Logout.Logout().logout()

    Login.Login().loginFail("admin", "123456", True)
    Login.Login().loginFail("李四", "123")
    Login.Login().loginFail("王五", "123456")

    Register.Register().registerSuccess("赵六", "abc", True)
    Login.Login().loginSuccess("赵六", "abc", True)
    Logout.Logout().logout(True)
    Register.Register().registerFail("admin", "qwe", True)

    Login.Login().loginSuccess("admin", "123", True)
    Index.Index().alreadyLogin(True)
    Index.Index().notLogin(True)

    Questions.Questions().showQuestions(True)
    Question.Question().showQuestion(True)

    ojDriver.driver.quit()

四、项目总结

经过上述的测试后,现在项目整体的功能没有出现大的问题,在测试过程中发现的一些小 Bug也都修复完成。可见通过系统性测试可以更好的发现 Bug,从而来完善我们的项目。

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

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

相关文章

【命令操作】信创终端系统上timedatectl命令详解 _ 统信 _ 麒麟 _ 方德

原文链接:【命令操作】信创终端系统上timedatectl命令详解 | 统信 | 麒麟 | 方德 Hello,大家好啊!今天给大家带来一篇关于如何在信创终端系统上使用timedatectl命令的详细介绍。timedatectl 是Linux系统中非常实用的时间管理工具,…

JMeter模拟并发请求

PostMan不是严格意义上的并发请求工具,实际是串行的,如果需要测试后台接口并发时程序的准确性,建议采用JMeter工具。 案例:JMeter设置20个并发卖票请求,查看后台是否存在超卖的情况 方式一:一共10张票&…

大数据-177 Elasticsearch Query DSL - 聚合分析 指标聚合 桶聚合

点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…

Excel重新踩坑3:条件格式;基本公式运算符;公式中的单元格引用方式;公式菜单栏其他有用的功能说明;

0、前言:以下内容是学习excel公式的基础内容。 1、需求:将表格特定区域中数值大小大于等于30,小于等于80的单元格,颜色填充为红色,大于80的,颜色填充为黄色。 新建规则之后也可以通过该功能清除规则。 2、基…

【JavaEE初阶】网络编程TCP协议实现回显服务器以及如何处理多个客户端的响应

前言 🌟🌟本期讲解关于TCP/UDP协议的原理理解~~~ 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客 🔥 你的点赞就是小编不断更新的最大动力 🎆那么废话不多说…

【重学 MySQL】六十六、外键约束的使用

【重学 MySQL】六十六、外键约束的使用 外键约束的概念关键字主表和从表/父表和子表外键约束的创建条件外键约束的特点外键约束的创建方式外键约束的删除外键约束的约束等级外键约束的级联操作外键约束的示例外键约束的作用开发场景阿里开发规范 在MySQL中,外键约束…

免费开源的微信开发框架

近年来,随着人工智能技术的快速发展,聊天机器人在各个领域得到了广泛的应用。在社交媒体中,自动回复成为了一个流行的功能,让用户可以方便地与机器人进行互动。gewe框架,一个开源的微信聊天机器人框架,实现…

Android 10.0 Camera2 拍照镜像功能实现

1.前言 在10.0的系统rom定制化开发中,在进行camera2的相关拍照功能开发中,在某些时候会遇到拍照照片 左右镜像的问题,就是照片左半边和右半边是反的,所以就需要在拍照的时候保存图片的时候实现 左右镜像功能,接下来就来分析下拍照保存图片的流程 2.Camera2 拍照镜像功能实…

银行数字化转型导师坚鹏:2025年银行开门红8大思考

2025年银行开门红8大思考:与2024年相比有哪些新的变化与不同? 1. ‌员工:从认清现实到重塑信心‌ 经济下行周期开启,叠加外部不稳定、不确定因素增加,让很多员工不适应、不习惯,甚至产生躺平心态。2025年…

信息学奥赛复赛复习18-CSP-J2022-01解密-二分答案、二分找边界、二分时间复杂度、二分求最小

PDF文档回复:20241017 1 P8814 [CSP-J 2022] 解密 [题目描述] 给定一个正整数 k,有 k 次询问,每次给定三个正整数 ni,ei,di,求两个正整数 pi,qi,使 nipiqi、eidi(pi−1)(qi−1)1 [输入格式] 第一行一个正整数 k,表…

leetcode动态规划(十)-0-1背包理论基础(一维数组)

一维dp数组(滚动数组) leetcode中无纯0-1背包问题,可从卡码网上查看题目46.0-1背包问题 一维数组来源于二维数组,其本质是对一维数组进行压缩了,压缩后需要注意在进行背包容量循环的时候采用后序遍历,而不…

Linux系统基础-进程间通信(3)_模拟实现匿名管道

个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 Linux系统基础-进程间通信(3)_模拟实现匿名和命名管道 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记,欢迎大家在评论区交流讨论&a…

强心剂!EEMD-MPE-KPCA-LSTM、EEMD-MPE-LSTM、EEMD-PE-LSTM故障识别、诊断

强心剂!EEMD-MPE-KPCA-LSTM、EEMD-MPE-LSTM、EEMD-PE-LSTM故障识别、诊断 目录 强心剂!EEMD-MPE-KPCA-LSTM、EEMD-MPE-LSTM、EEMD-PE-LSTM故障识别、诊断效果一览基本介绍程序设计参考资料 效果一览 基本介绍 EEMD-MPE-KPCA-LSTM(集合经验模态分解-多尺…

无人机电机损耗!

一、电机损耗类型 机械损耗: 主要由于电机的旋转部件(如转子、轴承等)在运转过程中产生的摩擦和磨损。 长时间运行或不当维护可能加剧这种损耗。 电气损耗: 包括电阻损耗、铁芯损耗和杂散损耗等。 这些损耗主要由电流通过电…

Golang | Leetcode Golang题解之第491题非递减子序列

题目: 题解: var (temp []intans [][]int )func findSubsequences(nums []int) [][]int {ans [][]int{}dfs(0, math.MinInt32, nums)return ans }func dfs(cur, last int, nums []int) {if cur len(nums) {if len(temp) > 2 {t : make([]int, len(…

未来AI的学习能力会达到怎样的水平?

​ 大家好,我是Shelly,一个专注于输出AI工具和科技前沿内容的AI应用教练,体验过300款以上的AI应用工具。关注科技及大模型领域对社会的影响10年。关注我一起驾驭AI工具,拥抱AI时代的到来。 AI工具集1:大厂AI工具【共2…

Leetcode—192. 统计词频【中等】(Shell)

2024每日刷题(188) Leetcode—192. 统计词频 实现代码 # Read from the file words.txt and output the word frequency list to stdout. cat words.txt | tr -s \n | sort | uniq -c | sort -nr | awk {print $2, $1}运行结果 之后我会持续更新&…

学习threejs,通过THREE.Raycaster给模型绑定点击事件

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.Raycaster光线投射概…

DirectX11:Position Based Fluid

前言 这是我本科毕业设计项目,使用DirectX11实现一个基于PBD的流体模拟仿真,同时也算是补了Games101的大作业了。 阅读本文假设你对以下内容比较熟悉: 流体模拟:Smoothed Particle Hydrodynamics 流体模拟:Neighbor…