基于Python + SQL server 实现(GUI)原神圣遗物管理与角色数值模拟系统

♻️ 资源

大小: 22.7MB

➡️ 资源下载: https://download.csdn.net/download/s1t16/87430310

原神圣遗物管理与角色数值模拟系统

一、游戏装备管理与数值模拟系统

二、系统概述

原神作为一款当下热门的游戏,有着较为丰富的装备系统和角色属性,该系统旨在辅助用户管理游戏装备,并对游戏角色进行模拟装配。系统通过复杂的数值计算帮助用户查看装配装备后的角色属性,如攻击力、暴击率、暴击伤害等,从而方便玩家对角色进行装备选择和强度评估。原神装备分为武器和圣遗物,圣遗物按装配部位又可进一步分为花、羽毛、沙漏、杯子、头盔五种。玩家拥有的每个角色只能装配一把武器和五个不同部位的圣遗物。武器拥有名称、主属性、副属性、技能信息,圣遗物拥有装配部位、类型、名称、等级、主属性、副属性信息。武器和圣遗物的详细信息可见数据库中表的属性定义。

三、系统功能需求

系统应提供四大功能模块,分别为圣遗物背包管理、武器图鉴、角色模拟装配、登录系统,此外,系统应具有良好的 GUI 交互界面,方便用户使用。

3.1 圣遗物背包管理

考虑到应用的实际用途及意义,由于原神中五星以下的圣遗物仅作为强化材料使用,并无实际用途,故圣遗物背包仅管理游戏中的五星级圣遗物。

用户能在圣遗物管理界面浏览仓库中拥有的圣遗物,圣遗物用缩略图展示,用户能在缩略图中直观地看到圣遗物的名称、等级、外观、主属性、副属性、是否已装备等信息。

用户能向仓库中添加圣遗物,添加界面允许用户输入圣遗物的类型、等级、属性等信息。

用户能将圣遗物装配给角色,该部位已装配圣遗物的角色不能再进行装配。

用户能删除仓库中的圣遗物,删除分为单选删除与批量清空。

用户能筛选圣遗物,筛选条件包括圣遗物的类型、装配部位、具体拥有的属性类型,且能组合不同的条件进行筛选。

用户能对圣遗物进行排序,排序功能分为等级正序、等级逆序、按装配部位分组排序、按类型分组排序,其中按装配部位排序和按类型排序是互斥的。

用户能将外部的圣遗物数据批量导入数据库。

3.2 武器图鉴

该系统收纳原神中的五星级武器,因武器数量少,玩家在游戏中没有管理需求,故需提供查询功能,方便用户进行合理地角色装配。

用户可在武器图鉴界面浏览游戏中的武器。

武器以图片形式展示,用户可单击武器图片,在界面右侧查看武器的详细信息。

3.3 角色装配模拟

用户可在角色装配模拟界面添加角色,新添加的角色默认无装备,相同角色在仓库中不能存在多个。

用户可为仓库中的角色装配或卸载武器和圣遗物。

用户能查看角色的属性值,新角色入库后,属性为游戏中该角色 90 级的基本属性,角色的属性值会随着武器,圣遗物的装配和卸下而动态变化。

用户能删除仓库中的角色,删除功能分为单选删除与批量清空。

3.4 登录系统

用户拥有自己的账户信息,每次启动该系统前需要输入登录信息连接数据库。

系统能根据用户的登录信息,用后端数据库的数据初始化用户仓库,即用数据库信息在前端界面恢复用户数据。

用户输入了错误的账户信息,系统能提示用户信息有误,需要重新输入信息。

四、数据库设计

4.1 ER 图

图 1 是该系统的实体-关系图,由图可见,该系统共有三个实体,分别为角色、圣遗物、武器。一名角色可以装备一把武器和多个圣遗物,一个圣遗物仅能被一名角色装配,一把武器也仅能被一名角色装配。武器、圣遗物在被同一角色装备后也建立了关联关系,故实体间为三元关联关系。

角色装配了武器和圣遗物后会拥有不同的属性,如生命值增幅、元素伤害加成、物理伤害加成等。如同学生选修课程后拥有选修的成绩是选修关系的属性,角色在装配武器和圣遗物后具有的属性是装备关系的属性。

注意到装备关系中存在"攻击力",而不存在"生命值","防御力"这两个属性,这是因为角色在装备武器后,自身的基础攻击力会发生变化,而基础生命值、基础防御力不变,仍属于角色的基础属性。生命值增幅、攻击力增幅等是圣遗物带来的属性,由于原神的伤害计算机制,他们不算作角色的基础属性。

五、数据库的逻辑结构设计

针对该系统,主要采取关系数据库的逻辑结构,它是一种按行与列排列的具有相关信息的逻辑组。数据库中建立了 Assemble(装配表)、Character(角色表)、Relics(圣遗物表)、Weapon(武器表)共 4 张表,视图 Character_Panel(角色面板)。

各表、视图的关系模式如下:

Character(string Name, int Life, int Attack, int Defense, string Properties, real Value);Weapon(string Name, int Attack, string Properties, real value, string skill)Relics(int id, string position, string setName, string detailName, string mainTagname, real mainTagvalue, string Tagname_1, real value_1, string Tagname_2, real value_2, string Tagname_3, real value_3, string Tagname_4, real value_4, int grade, string equipped)Assemble(string Name, string Weapon, int Flower, int Feather, int Sand, int Cup, int Head, int Life, int Attack, int Defense, int IncreaseLife, int IncreaseAttack , int IncreaseDefense , real LifePercentage, real AttackPercentage , real DefensePercentage , int Mystery, real Criticalhit, real Criticaldamage, real Treatment, real Efficiency, real Fire, real Water, real Thunder, real Wind, real Ice, real Rock, real Physics)Character_Panel(string Name, string Weapon, int Flower, int Feather, int Sand, int Cup, int Head, int Life, int Attack, int Defense, int Mystery, real Criticalhit, real Criticaldamage, real Treatment, real Efficiency, real Fire, real Water, real Thunder, real Wind, real Ice, real Rock, real Physics)

各表详细逻辑结构设计见表 1.

|-----------|-------------------|-----------|---------------|-----------|----|----------------|
| 实体 | 属性 | 描述 | 数据类型 | 完整性约束 | 主码 | 外码 |
| Character | Name | 姓名 | nvarchar(10) | NOT NULL | 是 | / |
| Character | Life | 生命值 | int | NOT NULL | / | / |
| Character | Attack | 攻击力 | int | NOT NULL | / | / |
| Character | Defense | 防御力 | int | NOT NULL | / | / |
| Character | Properties | 属性 | nvarchar(8) | NOT NULL | / | / |
| Character | Value | 属性值 | real | NOT NULL | / | / |
| Weapon | Name | 名称 | nvarchar(10) | NOT NULL | 是 | / |
| Weapon | Attack | 攻击力 | int | NOT NULL | / | / |
| Weapon | Properties | 属性 | nvarchar(8) | NOT NULL | / | / |
| Weapon | Value | 属性值 | real | NOT NULL | / | / |
| Weapon | skill | 技能 | nvarchar(500) | NOT NULL | / | / |
| Relics | Id | 主键 | Smallint | NOT NULL | 是 | / |
| Relics | position | 装配部位 | nvarchar(7) | NOT NULL | / | / |
| Relics | setName | 类型 | nvarchar(7) | NOT NULL | / | / |
| Relics | detailName | 名称 | nvarchar(9) | NOT NULL | / | / |
| Relics | mainTagname | 主属性 | nvarchar(19) | NOT NULL | / | / |
| Relics | mainTagvalue | 主属性值 | Real | NOT NULL | / | / |
| Relics | Tagname_1 | 副属性 1 | nvarchar(19) | /; | / | / |
| Relics | value_1 | 副属性 1 属性值 | Real | /; | / | / |
| Relics | Tagname_2 | 副属性 2 | nvarchar(19) | /; | / | / |
| Relics | value_2 | 副属性 2 属性值 | real | /; | / | / |
| Relics | Tagname_3 | 副属性 3 | nvarchar(19) | /; | / | / |
| Relics | value_3 | 副属性 3 属性值 | real | /; | / | / |
| Relics | Tagname_4 | 副属性 4 | nvarchar(19) | /; | / | / |
| Relics | value_4 | 副属性 4 属性值 | real | /; | / | / |
| Relics | Grade | 等级 | Smallint | NOT NULL | / | / |
| Relics | equipped | 是否装备 | nvarchar(8) | / | / | / |
| Assemble | Name | 姓名 | nvarchar(10) | NOT NULL | 是 | Character.Name |
| Assemble | Weapon | 武器 | nvarchar(10) | / | / | Weapon.Name |
| Assemble | Flower | 花 | Smallint | / | / | Relics.id |
| Assemble | Feather | 羽毛 | Smallint | / | / | Relics.id |
| Assemble | Sand | 沙漏 | Smallint | / | / | Relics.id |
| Assemble | Cup | 杯子 | Smallint | / | / | Relics.id |
| Assemble | Head | 头盔 | Smallint | / | / | Relics.id |
| Assemble | Life | 基础生命值 | Int | NOT NULL | / | / |
| Assemble | Attack | 基础攻击力 | Smallint | NOT NULL | / | / |
| Assemble | Defense | 基础防御力 | Smallint | NOT NULL | / | / |
| Assemble | Mystery | 元素精通 | Smallint | 默认值为 0 | / | / |
| Assemble | Criticalhit | 暴击率 | Real | 默认值为 0.05 | / | / |
| Assemble | Criticaldamage | 暴击伤害 | Real | 默认值为 0.5 | / | / |
| Assemble | Treatment | 治疗加成 | Real | 默认值为 0 | / | / |
| Assemble | Efficiency | 元素充能效率 | Real | 默认值为 1 | / | / |
| Assemble | Fire | 火元素伤害加成 | Real | 默认值为 0 | / | / |
| Assemble | Water | 水元素伤害加成 | Real | 默认值为 0 | / | / |
| Assemble | Thunder | 雷元素伤害加成 | Real | 默认值为 0 | / | / |
| Assemble | Wind | 风元素伤害加成 | Real | 默认值为 0 | / | / |
| Assemble | Ice | 冰元素伤害加成 | Real | 默认值为 0 | / | / |
| Assemble | Rock | 岩元素伤害加成 | Real | 默认值为 0 | / | / |
| Assemble | Physics | 物理伤害加成 | Real | 默认值为 0 | / | / |
| Assemble | IncreaseLife | 生命值增幅 | Smallint | 默认值为 0 | / | / |
| Assemble | IncreaseAttack | 攻击力增幅 | Smallint | 默认值为 0 | / | / |
| Assemble | IncreaseDefense | 防御力增幅 | Smallint | 默认值为 0 | / | / |
| Assemble | LifePercentage | 生命值增幅百分比 | Real | 默认值为 0 | / | / |
| Assemble | AttackPercentage | 攻击力增幅百分比 | Real | 默认值为 0 | / | / |
| Assemble | DefensePercentage | 防御力增幅百分比 | real | 默认值为 0 | / | / |

圣遗物表的记录不能超过 1000 条,具体操作触发器实现。视图的定义在下文详细说明,这里不作阐述。各外键名称如图 2 所示。

六、数据库物理设计

为了实现对数据的快速读取,采用 SQL server 提供的聚集索引。在 Assemble 表、Character 表、Relics 表、Weapon 表的主键上建立了聚集索引,用以加快查询速度。

由于该系统为用户提供排序功能,在 SQL 语句中会对某些列使用 order by 字句,故在 Relics 表的 grade、setName、position 属性列上建立了非聚集索引,提高了聚集索引不涵盖的频繁使用的属性的查询性能,用以加快排序速度。

七、详细设计与实现

7.1 数据库事务的定义与实现

事务作为数据库库的操作序列,可以包含一条或多条 SQL 语句。该系统使用 SQL server 提供的隐式事务,即 SQL server 在 SQL 语句前自动加上 begin transaction,而语句中需显式使用 commit 提交事务或 rollback transaction 回滚事务。

在 python 语言中定义 SQL 事务的方式如下文代码所示,在插入、删除、修改等 SQL 语句后加入 commit 语句提交本次操作,若语句有误,则引发 except 异常,将事务回滚。而对于 select 语句,无需 commit 提交语句即可执行。

圣遗物装备

def update_equipped(self, ID, character_name):

复制代码
sql = "update Relics set equipped = '%s' where id = '%d';commit" %(character_name, int(ID))
try:
  self.cursor.execute(sql)
except:
  self.conn.rollback()

该系统采用面向对象方法设计。类 Datamanage 负责与数据库进行交互,主要的数据库事务均定义在此类中;类 gui 负责绘制 GUI 界面,在该类中创建类 Datamanage 的对象,调用该类中与数据库交互的方法,从而实现了用户在可交互界面与后端数据库的交互功能。

7.1.1 添加圣遗物

首先在 GUI 界面绘制添加圣遗物界面,用户可在该界面选择圣遗物的名称、等级、主属性名,输入主属性值,添加副属性。各输入框均使用 python 内置的 tkinter GUI 库绘制。

界面的提交按钮与函数 relics_save()绑定,当用户点击提交按钮后,该函数从界面获取用户的输入值,调用函数 add_button_Cmd()在界面上绘制圣遗物缩略图,将该缩略图对象插入到 self.relic_list 列表中,然后调用 Datamanage 类的函数 data.insert_relics()将信息插入数据库。

函数 data.insert_relics()首先对用户添加的副词条个数进行统计,然后根据副词条个数的不同,选择执行不同的事务。

插入操作的事务之一定义如下,该 SQL 语句在用户添加三个副词条时被执行,它通过 insert 操作将用户输入的圣遗物信息插入到 Relics 表,实现方法是采用 values()方法将 python 中的变量值传入到 SQL 的变量。

复制代码
sql = "insert into Relics(id, position, setName, detailName, mainTagname, mainTagvalue,Tagname_1, value_1,Tagname_2, value_2,Tagname_3, value_3, grade)values('%d','%s','%s','%s','%s','%f','%s','%f','%s','%f','%s','%f','%d');commit" %(attri_dic['id'], attri_dic['pos'], attri_dic['setName'], attri_dic['detailName'], attri_dic['mainTag_name'], float(attri_dic['mainTag_value']), Tag[0], Tag[1], Tag[2], Tag[3], Tag[4], Tag[5],int(attri_dic['level']))

7.1.2 删除圣遗物

该系统的 GUI 界面在每个圣遗物缩略图右上方提供菜单按钮,用户点击该按钮可选择删除或装备圣遗物。GUI 界面的每个圣遗物对象都由字典组成,列表 self.relic_list 包含界面上所有的圣遗物字典。每个字典有多个键-值对,如 new_relic'id'记录圣遗物在数据库中的主键,new_relic'num'记录圣遗物是列表中的第几项,new_relic'detailName'记录圣遗物的名称,new_relic'pos'记录圣遗物的装配部位,其余键值对均与 GUI 绘制相关,在此不作阐述。

用户点击圣遗物上的删除或装备按钮后,按钮将其所属字典中的 new_relic'num'信息作为参数传入触发函数,从而获取到用户点击的圣遗物对象在列表中的索引。

函数 formore_button_Cmd()根据索引值,在列表中找到该圣遗物的字典,从字典中获取圣遗物的 ID(主键),然后将其作为参数传入类 Datamanage 的函数 dele_single_relic()中。

函数 dele_single_relic()获得 ID 后,执行 SQL 删除语句从 Relics 表中将该圣遗物记录删除,该事务定义如下:

复制代码
sql = "delete from Relics where id = '%d';commit" % (int(ID))

系统的批量删除功能会将列表 self.relic_list 中的圣遗物对象全部销毁,并多次调用函数 dele_single_relic()删除数据库中的数据。

7.1.3 装配圣遗物

函数 relics_up()绘制了圣遗物装配窗口,从圣遗物字典中获取到圣遗物 ID,从 GUI 界面的输入控件中获取到要装配的角色姓名,当用户点击确认按钮后,触发函数 relics_up_chara(),将 ID 和姓名作为参数传入触发函数。

函数 relics_up_chara()负责更新 GUI 的角色装配界面,并调用类 Datamanage 的函数 update_equipped()更新数据库。

函数 update_equipped()获得 ID 和角色姓名后,执行 SQL 更新语句从修改 Relics 表的是否装配属性,该事务定义如下:

复制代码
sql = "update Relics set equipped = '%s' where id = '%d';commit" %(character_name, int(ID))

7.1.4 筛选并排序圣遗物

系统拥有圣遗物筛选窗口,筛选功能如图 3 所示,用户能同时选择圣遗物的类型、部位以及不多于两条属性进行筛选。GUI 界面还提供了按钮使用户能对筛选结果进行排序,排序方式分为按部位排序、按类型排序和按等级排序。

函数 update_select ()在用户关闭筛选窗口,或点击任何一个排序按钮后被执行,该函数从界面获取用户指令信息,将其传给类 Datamanage 的函数 screen_relics()中,并根据查询结果更新界面显示

函数 screen_relics()接收用户的筛选指令,返回从数据库中查得的圣遗物信息,下文代码为函数的查询部分节选。

复制代码
#筛选查询圣遗物
    #select_box为属性筛选条件、setName为类型筛选条件、pos为部位筛选条件
    #order为true代表用户选择等级正序,为false代表等级逆序。type_group为true代表按类型排序,pos_group为true代表按部位排序
    def screen_relics(self, select_box, setName, pos, order, type_group, pos_group):
        if setName == '全部':
            setName = '%'
        #将部位信息转换为数据库中的表示形式
        pos = self.pos_name_trans[pos]
        #按类型和部位查询,查询结果取交集
        sql = "select * from Relics where setName like '%s' INTERSECT select * from Relics where position like '%s'" % (setName, pos)
        #按属性查询,查询结果取交集
        for i in range(len(select_box)):
            #循环次数等于属性的个数
            if select_box[i] != '%':
                sql += " INTERSECT select * from Relics where mainTagname like '%s' or Tagname_1 like '%s' or Tagname_2 like '%s' or Tagname_3 like '%s' or Tagname_4 like '%s'" % (select_box[i],select_box[i],select_box[i],select_box[i],select_box[i])
        if type_group:
            #按类型排序
            sql += "ORDER BY setName"
        elif pos_group:
            #按装配部位排序
            sql += "ORDER BY position"
        if type_group == False and pos_group == False:
            #用户未选择部位和类型排序,仅按等级排序
            if order :
                #正序排序
                sql += " ORDER BY grade ASC"
            else:
                #逆序排序
                sql += " ORDER BY grade DESC"
        else:
            #用户选择了按部位排序或按类型排序
            if order :
                #正序排序
                sql += ",grade ASC"
            else:
                #逆序排序
                sql += ",grade DESC"
        self.cursor.execute(sql)
        results = ''
        results = self.cursor.fetchall()

该函数定义了 SQL 的查询语句,它将许多不同的筛选条件写入了一条 SQL 语句中,并对查询结果元组取交集,从而满足不同查询需求的组合。注意到用户可以在筛选窗口的下拉盒子中选择"全部",它对应 SQL 语言中的通配符"%",不对查询语句施加限制。

此外,按部位查询与按类型查询互斥,二者不能同时作为 order by 语句写入 SQL 语句中。

7.1.5 插入角色

用户在角色装配界面点击添加按钮后,可在拥有下拉盒子的窗口中选择要添加的角色,确认按钮与函数 add_character_button()绑定,该函数从下拉盒子中获取角色姓名,调用类 Datamanage 的函数 insert_character()将信息插入数据库,然后调用函数 add_character_frame()在 GUI 界面显示被添加的角色。与圣遗物的存储结构类似,GUI 上的角色装配对象作为字典被存入列表 self.assemble_list 中,字典中的 character_dic'character_name'存储角色姓名,列表中元素的数量与用户拥有的角色数量相同。

函数 insert_character()执行 SQL 插入语句将角色信息插入 Assemble 表,该事务的定义如下:

复制代码
sql = "insert into Assemble (Name) values('%s');commit" % (character_name)

7.1.6 角色装配武器

用户可给已添加的角色装配武器,函数 assemble_weapon()在用户点击装配武器按钮后被调用,该函数绘制了选择武器的 GUI 窗口,用户在该窗口通过下拉盒子选择武器,窗口的确认按钮与函数 weapon_up_commit()绑定,向该函数传入要装配武器的角色在列表中的索引。函数 weapon_up_commit()根据索引找到列表中的角色字典,通过查询字典中的角色名,确定武器被装配到哪个角色上;从下拉盒子中获取要装配的武器名称。该函数调用类 Datamanage 的函数 assemble_weapon()更新数据库,调用函数 assemble_weapon_visable()在 GUI 界面显示武器。

函数 assemble_weapon()执行 SQL 更新语句修改 Assemble 表中的 Weapon 属性,该事务的定义如下:

复制代码
sql = "update Assemble set Weapon = '%s' where Name = '%s';commit" %(weapon_name, character_name)

7.1.7 删除角色装配信息

用户可点击角色图框右上角的按钮删除角色,该角色的装配信息也随之消失。函数 assemble_formore_button_Cmd()与该按钮绑定,按钮将被删除的角色在列表中的索引作为参数传递给函数。函数 assemble_formore_button_Cmd()根据索引找到列表中的角色字典,通过查询字典获取被删除的角色名。该函数调用类 Datamanage 的函数 assemble_dele()更新数据库,调用 update_select()改变 GUI 界面圣遗物的装配状态,最后在 GUI 界面将角色装配记录删除。

函数 assemble_dele()执行 SQL 删除语句删除 Assemble 表中的一个元组,该事务的定义如下:

复制代码
sql = "delete from Assemble where Name = '%s';commit" % (character_name)

角色装配信息的批量删除按钮与函数 assemble_dele_option_Cmd()绑定,该函数销毁列表 self.assemble_list 中的所有对象,并多次调用函数 assemble_dele()从数据库中删除角色的装配记录。

7.1.8 角色卸载武器

卸载武器按钮与函数 assemble_weapon_dele()绑定,按钮将被卸载的武器所属于的角色在列表中的索引作为参数传递给函数。函数 assemble_weapon_dele()根据索引找到列表中的角色字典,通过查询字典获取被卸载武器的角色名。该函数调用类 Datamanage 的函数 weapon_down()更新数据库,然后更新 GUI 界面的武器信息。

函数 weapon_down()执行 SQL 更新语句将 Assemble 表中对应行的 Weapon 属性改为 NULL,该事务的定义如下:

复制代码
sql = "update Assemble set Weapon = NULL where Name = '%s';commit" %(character_name)

7.1.9 角色卸载圣遗物

卸载圣遗物按钮与函数 assemble_relics_dele()绑定,按钮将被卸载的圣遗物所属于的角色在列表中的索引和被卸载的圣遗物部位作为参数传递给函数。函数 assemble_relics_dele()根据索引找到列表中的角色字典,通过查询字典获取被卸载圣遗物的角色名。该函数调用类 Datamanage 的函数 relics_down()更新数据库,然后更新 GUI 界面的圣遗物信息,并把圣遗物背包界面中对应的圣遗物改为未装配状态。

函数 relics_down()执行 SQL 更新语句将 Assemble 表中对应行的圣遗物属性改为 NULL,事务定义如下:

复制代码
sql = "update Assemble set %s = NULL where Name = '%s';commit" %(pos, character_name)

注意到 pos 的取值共有 5 种情况,即五个部位的圣遗物,分别对应 Assemble 表中 Flower、Feather、Sand、Cup、Head 属性列。

7.1.10 查询属性面板视图

角色面板视图 Character_Panel 的各属性均从表中计算得到,具体定义见下文视图定义部分。用户可点击装配界面的角色头像,查看角色的面板属性值,函数 look_detail()与角色头像按钮绑定,按钮将被点击的角色姓名作为参数传递给函数。函数 look_detail()调用类 Datamanage 的函数 select_panel()从视图中查询角色的属性值,然后绘制 GUI 窗口显示角色的面板属性。

函数 select_panel()根据角色姓名到视图 Character_Panel 中查询角色面板属性,将查询结果作为返回值返回。该事务的定义如下:

复制代码
sql = "select * from Character_Panel where Name = '%s'" %(character_name)

7.1.11 查询武器面板属性

用户在武器图鉴界面可点击武器查看武器的详细属性,武器按钮与函数 show_weapon_detail()绑定。同圣遗物的存储方式相同,GUI 界面的每把武器也用字典存储,字典存放在列表 weapon_pic_list 中。如 new_weapon'num' 表示武器字典列表中的位置,new_weapon'Name'代表武器名称。武器按钮将被点击的武器列表中的索引作为参数传递给函数,函数 show_weapon_detail()根据索引找到列表中的武器字典,从中获取武器名称。函数调用类 Datamanage 的函数 select_weapon_detail()从数据库中查询武器的详细信息,然后将武器信息显示到 GUI 界面上。

函数 select_weapon_detail()执行 SQL 查询语句,从 Weapon 表中查询对应武器的详细信息。该事务的定义如下:

复制代码
sql = "select * from Weapon where Name = '%s'" %(weapon_name)

7.1.12 用户登录系统后的信息恢复

该系统支持用户登录功能,本质上是将 SQL server 的账号和密码作为系统的账号和密码,用户的成功登录代表其成功连接了数据库。系统需要从数据库中查询用户数据,将其恢复到 GUI 界面。

用户登录成功后,函数 login_commit()会调用函数 initialize_assemble()恢复角色装配信息,该函数调用类 Datamanage 的函数 select_assemble()从数据库中查询角色装配信息并在 GUI 界面进行渲染。

函数 select_assemble()执行 SQL 查询语句,从 Assemble 表中查询 Name, Weapon, Flower, Feather, Sand, Cup, Head 等属性并将查询结果作为返回值返回。该事务的定义如下:

复制代码
sql = "select Name, Weapon, Flower, Feather, Sand, Cup, Head from Assemble"

函数 initialize_assemble()调用类 Datamanage 的函数 select_relics_byid(),根据圣遗物的 id 查询圣遗物的装配部位和名称,从而在装配界面渲染圣遗物。

函数 select_relics_byid()执行 SQL 查询语句,根据 ID 从 Relics 表中查询 position, detailName 属性并将查询结果作为返回值返回。该事务的定义如下:

复制代码
sql = "select position, detailName from Relics where id = %d" %(int(ID))

用户在成功登录后,函数 login_commit()还会调用类 Datamanage 的函数 select_weapon()查询数据库中的武器名称,并通过武器名称确认武器图鉴界面要显示的武器,即将武器名称作为参数传递给函数 add_weapon(),函数 add_weapon()在武器图鉴界面显示武器按钮,恢复武器信息,如上文所述,用户可点击武器按钮进一步查看武器的详细信息。

函数 select_weapon()执行 SQL 查询语句,它从 Weapon 表中查询 Name 属性,并将查询结果作为返回值返回。该事务的定义如下:

复制代码
sql = "select Name from Weapon"

7.2 数据库视图的定义与实现

视图定义涉及原神的角色属性数值计算,现将其简要介绍:游戏中的角色生命值、攻击力和防御力属性由两部分组成,一部分是"白值",即基础属性值,生命值和防御力的"白值"仅由角色自身属性值决定,而攻击力"白值"是角色自身属性和武器基础攻击力之和。另一部分是"绿值",即角色突破,武器属性和圣遗物带来的增益值,增益有两种,分为静态增益和百分比增益,角色的最终面板属性值 = "白值" + 静态增益值 + "白值"× 百分比增益值。

视图 Character_Panel 建立在 Assemble 表上,具体定义如下:

复制代码
CREATE VIEW [dbo].[Character_Panel](Name,Weapon,Flower,Feather,Sand,Cup,Head,Life,Attack,Defense,Mystery,Criticalhit,Criticaldamage,Treatment,Efficiency,Fire,Water,Thunder,Wind,Ice,Rock,
                                    Physics)
AS
Select Name,Weapon,Flower,Feather,Sand,Cup,Head,Life + IncreaseLife + Life * LifePercentage,Attack + IncreaseAttack + Attack*AttackPercentage,
       Defense + IncreaseDefense + Defense * DefensePercentage,Mystery,Criticalhit,Criticaldamage,Treatment,Efficiency,Fire,Water,Thunder,Wind,Ice,Rock,Physics
       FROM Assemble;

可以看到,视图的大部分属性与 Assemble 表中的属性一致,而 Life 属性、Attack 属性、Defense 属性均由 Assemble 表的基础属性和增幅属性按上述计算公式计算得到。注意 Assemble 表中的 Attack 属性的属性是由 Character 表的 Attack 属性与 Weapon 表的 Attack 属性相加得到,具体操作由触发器实现。

7.3 数据库触发器的定义与实现

该系统在 Assemble 表上定义了dele_downRelics_downUp_attributeWeapon_DownWeapon_Up触发器,在 Relics 表上定义了Relics_upRelics_limit触发器,各触发器的定义代码篇幅较长,见附录。

7.3.1 Up_attribute 触发器

该触发器定义在基本表 Assemble 上,由 insert 操作触发。当用户向 Assemble 表中插入角色时,该触发器从 Character 表中查找与该角色姓名相同的记录,用 Character 表中角色的属性值初始化 Assemble 表中新增加角色的属性值。

由于 Assemble 表中的角色在被创建时各属性就拥有初始值,故在触发器中需要将 Character 中的属性值和 Assemble 表的属性值相加再赋值给 Assemble 表的属性,如生命值的更新语句:

复制代码
Declare @Name nvarchar(10);
select @Name = inserted.Name from inserted;
update Assemble
set Life = Life + (select Character.Life from Character, inserted where  inserted.Name = Character.Name)
           where Assemble.Name = @Name;

触发器首先声明@Name 变量,将其初始化为要插入角色的姓名。在 SQL server 中,inserted 表和 deleted 表分别对应 SQL 标准中的 NEWTABLE 和 OLDTABLE 表。之后使用 update 语句,用 Character 表的 Life 属性更新 Assemble 表的 Life 属性。

Attack 属性、Defense 属性的更新过程与 Life 属性相似。而对于角色的突破属性,则需要用多个 if-else 语句判断其类型。如"甘雨"的 Properties 属性为暴击伤害,"申鹤"的 Properties 属性为攻击力,触发器需要判断 Character 表的 Properties 属性类型,从而选择 Assemble 表中的相应属性列进行更新。

7.3.2 dele_down 触发器

该触发器定义在表 Assemble 上,由 DELETE 操作触发。当用户删除角色时,该触发器更新圣遗物装配属性,即找到被删除角色装配圣遗物的 id,在 Relics 表中将相同 id 圣遗物的 equipped 属性改为 NULL。触发器中的 update 语句定义如下:

复制代码
UPDATE Relics
set equipped = null
               where exists(Select * from deleted where id = Flower or id = Feather or id = Sand or id = Cup or id = Head);

圣遗物分为五个部位,因此在 select 子查询中需要判断五次以确定圣遗物的 id 和被删除角色所装配的圣遗物 id 是否相同。

7.3.3 Weapon_Up 触发器

该触发器定义在表 Assemble 上,由 UPDATE 操作触发。当用户为角色装配武器时,该触发器查询 Weapon 表,用被装配武器的属性值更新 Assemble 表中角色的属性值。

复制代码
/*确认是否修改了武器,找到增加的武器名称*/
Declare @weapon nvarchar(10);
select @weapon = inserted.Weapon
                 from inserted
                 where  inserted.Weapon is not null AND exists(Select * from deleted where deleted.Name = inserted.Name AND deleted.Weapon is null);

触发器首先查询 inserted 表和 deleted 表,将更新操作前后的 Weapon 属性进行对比,若 Weapon 属性更新前是空,更新后不是空,则@weapon 变量为被装配的武器名,说明 update 操作为角色装配了武器。

@weapon 变量不为空时,触发器查询 Weapon 表中名称属性与@weapon 的值相等的元组,用该元组的属性更新 Assemble 表的角色属性。更新攻击力属性的 SQL 语句如下:

复制代码
select @name = inserted.Name from inserted;
update Assemble
set Assemble.Attack = Assemble.Attack + (select Attack from Weapon where Weapon.Name = @weapon)
                      where Assemble.Name = @name;

对于武器的属性值,仍需要使用多个 if-else 语句判断其属性类型 Weapon.Properties,然后用其属性值 Weapon.Value 更新 Assemble 表中对应属性列的值。如若 Weapon.Properties 属性是"物理伤害加成",则需更新 Assemble 表的 Physics 属性列,执行的 SQL 语句如下:

复制代码
select @properties = Weapon.Properties from Weapon where Weapon.Name = @weapon
                     select @value = Weapon.Value from Weapon where Weapon.Name = @weapon
                                     if(@properties = '物理伤害加成')
                                         begin
                                         update Assemble
                                         set Assemble.Physics = Assemble.Physics + @value
                                                 where Assemble.Name = @name;
end

7.3.4 Weapon_Down 触发器

该触发器定义在表 Assemble 上,由 UPDATE 操作触发。当用户卸下角色装配的武器时,该触发器查询 Weapon 表,用被卸下武器的属性值更新 Assemble 表中角色的属性值。

复制代码
Declare @weapon nvarchar(10);
/*确认是否卸掉了武器*/
select @weapon = deleted.Weapon
                 from deleted
                 where deleted.Weapon is not null AND exists(select * from inserted where inserted.Name = deleted.Name AND inserted.Weapon is null);

触发器首先查询 inserted 表和 deleted 表,将更新操作前后的 Weapon 属性进行对比,若 Weapon 属性更新前非空,更新后为空,则@weapon 变量为被卸下的武器名,说明 update 操作为角色装配了武器。

@weapon 变量不为空时,触发器更新 Assemble 表的属性,具体操作与装配武器相同,仅需在代表武器属性值的@value 变量前加上负号,并将攻击力属性更新语句改为减法操作。

7.3.5 Relics_up 触发器

该触发器定义在 Relics 表上,由 UPDATE 操作触发。当用户将圣遗物装配给角色时,该触发器查询 Assemble 表,更新对应部位圣遗物的装配信息和因装配圣遗物而改变的角色属性值。

复制代码
Declare @pos nvarchar(10);
Declare @equip nvarchar(10);
Declare @id smallint
Declare @mainTagname nvarchar(19);
Declare @Tagname_1 nvarchar(19);
Declare @Tagname_2 nvarchar(19);
Declare @Tagname_3 nvarchar(19);
Declare @Tagname_4 nvarchar(19);
Declare @mainTagvalue real;
Declare @value_1 real;
Declare @value_2 real;
Declare @value_3 real;
Declare @value_4 real;
Select @pos = position from inserted
Select @equip = equipped from inserted
Select @id = id from inserted
Select @mainTagname = mainTagname from inserted
Select @Tagname_1 = Tagname_1 from inserted
Select @Tagname_2 = Tagname_2 from inserted
Select @Tagname_3 = Tagname_3 from inserted
Select @Tagname_4 = Tagname_4 from inserted
Select @mainTagvalue = mainTagvalue from inserted
Select @value_1 = value_1 from inserted
Select @value_2 = value_2 from inserted
Select @value_3 = value_3 from inserted
Select @value_4 = value_4 from inserted

首先,触发器需要获取被装配圣遗物的 id(主键),pos(装配部位),equip(要装配的角色名),以及主属性名,主属性值,副属性名和副属性值,通过判断 equip 属性是否变化来确定本次更新操作是否与圣遗物装配有关。其次,触发器根据装配部位的不同,更新 Assemble 表对应的属性列,比如被装配的圣遗物的 pos 属性为"flower",id 属性为"10001",则需将 Assemble 表中的 Flower 属性列更新为"10001"。该功能的 SQL 语句定义如下:

复制代码
if (@pos = 'flower' AND @equip is not null)
    begin
    update Assemble
    set Assemble.Flower = @id
                          where Assemble.Name = @equip;
end

然后,触发器需要判断圣遗物的主属性 mainTagname 的类型,从而确定在 Assemble 表中要更新的属性列,并用 mainTagvalue 更新该属性列。考虑到游戏中花的主属性只能为"生命值",羽毛的主属性只能为"攻击力",若被装配圣遗物的 pos(部位)是 flower(花)或 feather(羽毛),则主属性 mainTagname 的值是确定的,此时无需判断主属性的类型,只需更新 Assemble 表的 IncreaseLife 属性或 IncreaseAttack 属性,故将上述 SQL 语句修改如下:

复制代码
if (@pos = 'flower' AND @equip is not null)
    begin
    update Assemble
    set Assemble.Flower = @id
                          where Assemble.Name = @equip;
/*主词条添加*/
update Assemble
set Assemble.IncreaseLife = Assemble.IncreaseLife + @mainTagvalue
                            where Assemble.Name = @equip;
end

若被装配的是其他部位的圣遗物,则需要多个 if-else 语句判断该圣遗物主属性,比如被装配的圣遗物主属性是"元素精通",则需更新 Assemble 表的 Mystery 属性,该操作的 SQL 语句定义如下:

复制代码
if(@mainTagname = '元素精通')
    begin
    update Assemble
    set Assemble.Mystery = Assemble.Mystery + @mainTagvalue
                           where Assemble.Name = @equip;
end

最后,触发器需要判断圣遗物的副属性 Tagname_1、Tagname_2、Tagname_3、Tagname_4 的类型,并用 value_1、value_2、value_3、value_4 的属性值更新 Assemble 表中的属性列。考虑到游戏中同一圣遗物的副属性词条类型不能重复,触发器首先判断副属性可能拥有的所有词条类型,对每个类型的词条,依次判断该圣遗物的四个副属性类型是否与当前类型相同,进而更新 Assemble 表中的属性列。比如,依次判断四个副词条 Tagname_1~4 的值是否为"生命值百分比",若 Tagname_2 = "生命值百分比",则用 value_2 属性值更新 Assemble 表的 LifePercentage 属性列,该操作的 SQL 语句定义如下:

复制代码
if(@Tagname_1 = '生命值百分比')
    begin
    update Assemble
    set Assemble.LifePercentage = Assemble.LifePercentage + @value_1
                                  where Assemble.Name = @equip;
end
else if(@Tagname_2 = '生命值百分比')
    begin
    update Assemble
    set Assemble.LifePercentage = Assemble.LifePercentage + @value_2
                                  where Assemble.Name = @equip;
end
else if(@Tagname_3 = '生命值百分比')
    begin
    update Assemble
    set Assemble.LifePercentage = Assemble.LifePercentage + @value_3
                                  where Assemble.Name = @equip;
end
else if(@Tagname_4 = '生命值百分比')
    begin
    update Assemble
    set Assemble.LifePercentage = Assemble.LifePercentage + @value_4
                                  where Assemble.Name = @equip;
end

圣遗物的副属性词条共有十种,故触发器共有十条上述的 SQL 语句。

7.3.6 Relics_down 触发器

该触发器定义在 Assemble 表上,由 UPDATE 操作触发。当用户将角色的圣遗物卸下时,该触发器查询 Relics 表,更新 Relics 表中圣遗物的 equip(是否装配)属性,并由该圣遗物的主属性、副属性更新 Assemble 表中的角色属性值。

触发器首先需要判断更新操作是否卸下了圣遗物和被卸下圣遗物的部位,由于用户一次只能卸掉一个圣遗物,所以@idflower、@idfeather 等五个变量中,仅有一个是非空值,该操作的 SQL 语句定义如下:

复制代码
Declare @idflower smallint;
Declare @idfeather smallint;
Declare @idsand smallint;
Declare @idcup smallint;
Declare @idhead smallint;
/*一次只能卸掉一个圣遗物,所以仅有一个id是非空值*/
select @idflower = deleted.Flower
                   from deleted
                   where deleted.Flower is not null AND exists(select * from inserted where inserted.Name = deleted.Name AND inserted.Flower is null);
select @idfeather = deleted.Feather
                    from deleted
                    where deleted.Feather is not null AND exists(select * from inserted where inserted.Name = deleted.Name AND inserted.Feather is null);
select @idsand = deleted.Sand
                 from deleted
                 where deleted.Sand is not null AND exists(select * from inserted where inserted.Name = deleted.Name AND inserted.Sand is null);
select @idcup = deleted.Cup
                from deleted
                where deleted.Cup is not null AND exists(select * from inserted where inserted.Name = deleted.Name AND inserted.Cup is null);
select @idhead = deleted.Head from deleted
                 where deleted.Head is not null AND exists(select * from inserted where inserted.Name = deleted.Name AND inserted.Head is null);

然后,触发器找出非空变量,从而确定被卸下圣遗物的 id 属性,由该 id 属性搜索 Relics 表中的元组,将对应元组的 equipped 属性改为 NULL。

最后,触发器用该圣遗物再 Relics 表中的主、副属性值更新 Assemble 表对应的属性列,修改角色的各属性值,该部分操作与圣遗物装配触发器相似,仅需在圣遗物的主属性值,副属性值前加上负号。

7.3.7 Relics_limit 触发器

该触发器定义在 Relics 表上,由 INSERT 操作触发。当用户向 Relics 表中插入数据前,该触发器检查表中数据数量与插入数据的数量之和是否大于 1000,若大于 1000,将插入事务回滚。

八、数据库测试

为了产生充足的数据测试系统,借用了 NGA 上的"椰羊"圣遗物导出工具将圣遗物信息从游戏中批量导出,导出的信息保存在.json 文件中。该导出工具的下载链接如下:

用 python 编写程序将 JSON 文件中的信息批量插入数据库,具体实现方式是先读取 JSON 文件,再连接数据库,用 SQL 的语句将读取的信息插入到数据库中,具体代码见附录。

batchinsert.py 与 JSON 文件放在同一目录下,运行 batchinsert.py,即可将 JSON 文件导入数据库,本次测试共导入了 750 个圣遗物。

8.1 圣遗物添加功能测试

用户点击圣遗物管理界面右上角的添加按钮,在属性选择窗口添加名称为"焦灼的魔女帽"和"贤医之羽"的圣遗物,具体运行结果见下图所示,仓库中的圣遗物信息与用户输入的信息相符,注意到系统将带有百分比的数据乘以 100% 后显示。用 select 语句在数据库中查询可得相同的记录,其中 id 属性的信息为程序查询空闲 id 并自动分配。

8.2 圣遗物删除功能测试

8.2.1 单个删除功能

点击圣遗物缩略图右上角的菜单按钮,选择删除选项,该圣遗物被从背包中移除,用 select 语句在数据库中查询可见该记录已消失。

8.2.2 批量删除功能

现添加多个圣遗物,用 select 语句查询数据库,由下图可见已添加的圣遗物。

点击右上角的清空按钮,再次用 select 语句查询数据库,由下图可见查询结果为空。

8.3 圣遗物筛选功能测试

8.3.1 不施加筛选条件

点击筛选按钮,不选择任何筛选条件,关闭窗口,若数据库中的圣遗物记录过多,查询时应用窗口可能会产生轻微卡顿。筛选结果由下图所示。

8.3.2 施加所有筛选条件

现添加筛选条件,仅查询类别为炽热的炎之魔女,装配部位是羽毛,同时具有暴击率、暴击伤害属性词条的圣遗物,关闭窗口,筛选结果如下图所示:

8.3.3 鲁棒性测试

现选择三个属性筛选条件,关闭窗口,系统会产生错误提示,因为系统规定选择的增益属性条件不能多于两个,运行结果如下图所示:

8.4 圣遗物排序功能测试

8.4.1 按等级排序

改变筛选条件,查询类型为"翠绿之影"的所有圣遗物,查询结果默认按等级正序,运行结果如下图所示:

点击等级逆序按钮,系统将查询结果逆序排序,运行结果如下图所示:

8.4.2 按部位分组

点击按部位分组,系统将查询结果按 Relics 表的 pos 属性排序,运行结果如下图所示:

8.4.3 按类型分组

修改筛选条件,查询装配部位是杯子,拥有生命值、元素充能效率属性的圣遗物,然后点击按类型分组,系统将查询结果按 Relics 表的 setName 属性排序,运行结果如下图所示:

从结果可见,相同类型的圣遗物处于相邻位置,如图中五个吟游者之壶的类型都为"流浪大地的乐团"。

8.5 武器图鉴功能测试

点击左侧蓝色框内的第二个按钮,查看武器图鉴,系统运行结果如下图所示:

点击护摩之杖,系统到 Weapon 表中查询得到名称为"护摩之杖"的武器,将其详细信息展示在界面右侧,系统运行结果如下图所示:

8.6 角色装配模拟测试

点击左侧蓝色框内的第三个按钮,进入角色装配界面,系统运行结果如下图所示:

8.6.1 角色添加功能测试

点击右上角的添加按钮,可在弹窗中选择要添加的角色姓名,系统运行结果如下图所示:

选择阿贝多,点击确认,系统会将一个元组插入 Assemble 表,Name 属性是"阿贝多",由触发器Up_attribute查询 Character 表,根据查询结果自动填写角色的初始属性。系统运行结果如下图所示:

再次点击添加按钮,此时的下拉列表中已无选项"阿贝多",由于 Assemble 表把角色姓名作为主键,因此 GUI 界面的选项中删除了已添加的角色。选择"八重神子",点击确认按钮,系统运行结果如下图所示:

用 select 语句查询 Assemble 表,可以看到已添加的角色信息,系统运行结果如下图所示:

8.6.2 角色属性面板功能测试

点击阿贝多的头像,系统从视图中查询阿贝多的各项属性属性值,并在弹窗中显示给用户,运行结果如下图所示:

用 select 语句查询视图,并对比二者属性值,GUI 界面将部分属性乘以 100% 后用百分比展示,运行结果如下图所示:

8.6.3 角色武器装配测试

点击阿贝多头像右侧的加号按钮,可在弹窗中选择要装配的武器名称,选择武器"拨乱月白经津",运行结果如下图所示:

此时系统在 Assemble 表中更新了 Weapon 属性值,并由触发器Weapon_Up自动更新阿贝多的攻击力和暴击率属性。再次点击阿贝多头像查看角色面板,系统运行结果如下图所示:

用 select 查询语句查询视图,对比二者属性值,系统运行结果如下图所示:

8.6.4 角色武器卸载测试

点击武器下的卸载按钮,为角色卸下武器,此时系统将 Assemble 表的 Weapon 属性改为 NULL,激活触发器Weapon_Down,自动更新角色属性值,再次点击角色面板查看角色面板属性,发现与角色刚被添加时的属性值相同,系统运行结果如下图所示:

8.6.5 角色圣遗物装配测试

点击左侧蓝框内第一个按钮,回到圣遗物界面,筛选类别为"昔日宗室之仪",拥有"防御力百分比"和"元素充能效率"属性的圣遗物,系统运行结果如下图所示:

点击第一个宗室之花右上角的菜单按钮,选择装配,在弹出的窗口中选择阿贝多,此时系统将 Relics 表中对应圣遗物的 equip 属性修改为"阿贝多",激活触发器Relics_up,触发器更新 Assemble 表中角色的装配信息和属性值,系统运行结果如下图所示:

可以看到,圣遗物被装配后,右上角的菜单按钮被隐藏,因为系统规定已装配的圣遗物被卸下前不能再次装配给其他角色。

将图片中第一个宗室时计、宗室银瓮、宗室面具为阿贝多装备,为阿贝多装备武器斫风之刃,再次点击阿贝多头像,查看阿贝多的属性面板,系统运行结果如下图所示:

查看武器图鉴中斫风之刃的属性,通过属性计算公式可验证系统的数值计算是否正确。

生命值上限 = 13226(角色基础生命值) + 4780(宗室之花主属性) + 239(宗室银瓮副属性)+ 299(宗室面具副属性) = 18544

攻击力 = 251(角色基础攻击力) + 608(武器基础攻击力)+ (251 + 608) × 0.496(武器副属性)+ 18(宗室时计副属性) + (251 + 608) × 0.058(宗室时计副属性)+ 14(宗室银瓮副属性)= 1366.886

防御力 = 876(角色基础防御力)+ 876 × 0.131(宗室之花副属性)+ 876 × 0.087(宗室时计主属性)+ 876 × 0.087(宗室银瓮主属性)+ 876 × 0.066(宗室面具副属性)+ 23 (宗室面具副属性)= 1223.996

其余属性值的计算为简单的加法运算,再次不多赘述。

8.6.6 角色圣遗物卸载测试

回到圣遗物背包界面,点击第二个宗室之花,发现装配选项中没有"阿贝多",因为一名角色在同一部位只能装备一个圣遗物,将该圣遗物为八重神子装备。

在角色装配界面,点击圣遗物下方的卸载按钮,卸载宗室之花和宗室时计,此时触发器Relics_down被激活,触发器改变 Assemble 表中的角色属性值,并将 Relics 表对应圣遗物的 equip 属性改为 NULL。点击角色属性面板,可以看到角色属性值发生了变化。系统运行结果如下图所示:

再次查看圣遗物管理界面,可以看到被卸下的圣遗物右上角的按钮再次出现。

8.6.7 角色删除测试

点击角色装配模拟界面,角色框右上角的菜单按钮,选择删除,此时系统删除 Assemble 表中对应的角色记录,激活触发器dele_down,触发器查询被删除角色身上装配的圣遗物,到 Relics 表中将对应的圣遗物的 equip 属性改为 NULL。因此在圣遗物管理界面,对应的圣遗物重新显示右上角的菜单按钮,系统运行结果如下图所示:

8.6.8 角色批量删除测试

在角色装配界面添加多个角色,系统运行结果如下图所示:

用 select 语句查询视图,可见添加的角色装配信息和属性值。系统运行结果如下图所示:

查看圣遗物管理界面,被装配的圣遗物的菜单按钮被隐藏,系统运行结果如下图所示:

点击角色装配界面右上角的清空按钮,系统在后端将 Assemble 表清空,并在前端显示圣遗物右上角的菜单按钮。运行结果如下图所示:

8.7 登录系统与数据恢复测试

8.7.1 登录系统

用户打开系统时,进入登录界面,用户需要在登录界面输入 SQL server 中 SQL 身份认证的账号和密码,此外还需要输入要连接到的数据库服务器和 tcp 动态端口。服务器名称可在 SQL 启动界面查看,tcp 动态端口可在 SQL server 配置管理器中查看,如下图所示。

将登录信息输入到登录窗口后,系统会连接 SQL server 服务器,若连接成功,进入到圣遗物管理界面。登录窗口如下图所示:

若连接失败,提示用户输入信息有误,用户需要重新输入登录信息,运行结果如下图所示:

注意系统默认用户在 SQL server 数据库中有名为 genshi 的数据库,若不存在该数据库则无法登录系统。

8.7.2 用户登录后的数据恢复

在圣遗物管理界面筛选类型为"平息鸣雷的尊者"的圣遗物,该类型的圣遗物在数据库中仅存在一条信息,系统运行结果如下图所示:

现添加几条类型为"平息鸣雷的尊者"的圣遗物,系统运行结果如下图所示:

在角色装配界面新增几名角色,并为其装配圣遗物,系统运行结果如下图所示:

用 select 语句查询新添加角色的装配信息与圣遗物的信息,系统运行结果如下图所示:

点击右上角关闭窗口并退出系统,重新启动并登录系统,系统运行结果如下图所示:

登录后圣遗物界面为空,筛选类型为"平息鸣雷的尊者"的圣遗物,系统运行结果如下:

查看角色装配界面,该界面中角色的装配信息在系统登录成功后已自动渲染。

相关推荐
Crazy_eater3 小时前
Mysql(6)--基础查询
数据库·mysql
是有头发的程序猿3 小时前
电商自动化实战:淘宝/天猫item_get商品详情API全量采集教程(Python源码)
java·python·自动化
_不会dp不改名_3 小时前
python-opencv环境搭建
开发语言·python·opencv
勇往直前plus3 小时前
智能体记忆概述
人工智能·python·ai
古韵3 小时前
告别手写分页逻辑:usePagination 从 50 行到 3 行
java·前端
HappyAcmen3 小时前
9.复盘API全套流程
开发语言·python
北城以北88884 小时前
Quartz定时任务
java·spring boot·intellij-idea
添砖java‘’4 小时前
MySQL事务
数据库·mysql
zh路西法4 小时前
【Linux 串口通信】基于 C++ 多线程的同步/异步串口实现
linux·运维·c++·python