吾爱汇编

 找回密码
 立即注册

QQ登录

绑定QQ避免忘记帐号

查看: 72|回复: 1

帮找代码数据错乱的原因

[复制链接]
cxq97241916 发表于 2026-4-18 16:00 | 显示全部楼层 |阅读模式

本站严厉禁止求脱求破行为(包含无自我分析直接求思路),如发现此类求助主题请点击“举报”,让我们共同维护优质的学习环境!


200HB
# 比赛编排系统 - 场次数据处理模块 技术文档
## 一、模块概述
本模块负责**比赛场次数据的生成、日期分配和编号编排**。涉及的核心功能是:从抽签完成后的选手数据出发,生成完整的对阵场次表(ChangciInfo),并支持按日期分批处理不同轮次的比赛。
### 涉及的数据库表
| 表名 | 用途 |
|------|------|
| `BisaiGongjinjiBie` | 轮次结构表(如1/16决赛、1/8决赛、复1、决12等)——**只存结构,不存具体场次** |
| `ChangciInfo` | 具体场次数据表(每场比赛一条记录,包含日期、台号、红蓝方选手等) |
| `JibieLunciRiqi` | 级别-日期-轮次类型分配表(如"男自55kg在4月18日进行淘汰赛") |
| `JibieRiqiSetList` | 级别-日期-轮次明细列表(由"加入自动处理列表"生成,用于驱动场次生成) |
| `DuizhanTu` | 对战图数据(树形结构的父子关系) |
| `XuanshouCanshai` | 选手参赛参数表 |
| `XuanshouCanshaiRecord` | 选手参赛记录表 |
| `GudingBianpaiDuizhenBiao` | 固定编排对照表(预定义的对阵模板) |
---
## 二、完整操作流程(按用户实际操作顺序)
```
步骤1: 抽签 → 步骤2: 生成全部场次数据 → 步骤3: 设置日期(第一步) → 步骤4: 第二步更新
→ 步骤5: 加入自动处理列表 → 步骤6: 开始处理自动列表(button8_Click)
→ 步骤7: 再次加入自动处理列表 → 步骤8: 再次开始处理自动列表(button8_Click)
```
---
## 三、每个步骤对应的代码位置和逻辑
### 步骤1:抽签
**文件**: `Frm单复活抽签.cs`
**作用**: 为每个选手分配签号(Qianhao),写入 `XuanshouInfo` 表。
---
### 步骤2:"生成全部场次数据"按钮
**文件**: [Frm单复活抽签.cs 第1094-1143行](../../SJBS.Admin/系统设置/Frm单复活抽签.cs#L1094-L1143)
**方法**: `button2_Click()``CreateChangci()`
```csharp
// Frm单复活抽签.cs 第1107-1127行
private void CreateChangci(string jibieName = "")
{
    new DALJibieLunciRiqi().DeleteAll();  // ⚠️ 先清空所有日期分配
    foreach (BisaiGongjiJi curBisaiGongjiJi in lstBisaiGongjiJi)
    {
        new DALBisaiGongjinjiBie().CleanTheJibieMx(curBisaiGongjiJi.Id); // ⚠️ 清空该级别所有数据
        ResultMsg msg = SJBSHelper.JibieCHulicaozuo(curBisaiGongjiJi);   // 重新生成轮次结构
    }
}
```
**⚠️ 关键行为**: 此步骤会**删除并重建**以下数据:
- `ChangciInfo`(所有场次)
- `BisaiGongjinjiBie`(所有轮次结构)
- `DuizhanTu`(所有对战图)
- `XuanshouCanshai` / `XuanshouCanshaiRecord`
- `JibieRiqiSetList` / `JibieAndRiqi`
然后调用 `SJBSHelper.JibieCHulicaozuo()` 只重新生成 `BisaiGongjinjiBie`(轮次结构),**不生成 ChangciInfo(具体场次)**
**CleanTheJibieMx 的SQL**([DALBisaiGongjinjiBie.cs 第55-88行](../../DAL/DALBisaiGongjinjiBie.cs#L55-L88)):
```sql
DELETE XuanshouCanshai WHERE ... -- 删除参数据
DELETE XuanshouCanshaiRecord WHERE ... -- 删除参数记录
DELETE JibieRiqiSetList WHERE ... -- 删除时间明细
DELETE JibieAndRiqi WHERE ... -- 删除时间主表
DELETE ChangciInfo WHERE JibieId = {id} -- 删除场次表 ⚠️⚠️⚠️
DELETE BisaiGongjinjiBie WHERE JibieId = {id} -- 删除轮次结构
DELETE DuizhanTu WHERE JibieId = {id} -- 删除对战图
```
---
### 步骤3:"设置场次数据"(第一步 - 设置日期和轮次类型)
**作用**: 用户选择日期(如4月18日、4月19日),并为每个日期分配轮次类型(淘汰赛/复活赛/决赛)。
**写入**: `JibieLunciRiqi` 表。
**示例**: "男自55kg 在 4月18日 进行 淘汰赛"
---
### 步骤4:"第二步更新"
**文件**: [Frm设置第二步.cs](../../SJBS.Admin/比赛管理/Frm设置第二步.cs)
**作用**: 界面刷新,将第一步设置的日期加载到左侧列表区域。不操作数据库。
---
### 步骤5:"加入自动处理列表"按钮
**文件**: [Frm设置第二步.cs 第283-391行](../../SJBS.Admin/比赛管理/Frm设置第二步.cs#L283-L391)
**方法**: `button1_Click()`
```csharp
// 核心逻辑:
// 1. 从 JibieLunciRiqi 获取当前选中日期的所有级别-轮次分配
List<JibieLunciRiqi> lstJibieLunciRiqi = new DALJibieLunciRiqi().GetListByRiqi(selectedDate);
// 2. 对每个轮次分配,找到对应的 BisaiGongjinjiBie(轮次结构)
// 3. 创建 JibieRiqiSetList 对象,写入内存列表 lstLeftJibieRiqiSetList
//    (此时还只是内存数据,未写入数据库)
newJibieRiqiSetList.JitiShijian = jibieLunci.Riqi + ListBTimeSet.SelectedItem.ToString(); // 日期+时间
newJibieRiqiSetList.Taihao = ListBTaihao.SelectedItem.ToString();                       // 台号
newJibieRiqiSetList.JibieMxId = curBisaiGongjinjiBie.Id;                             // 关联到轮次结构ID
```
**&#9888;&#65039; 重要**: 此步骤**只写内存**`lstLeftJibieRiqiSetList`),**不写数据库**
---
### 步骤6:"开始处理自动列表"按钮(第一次 - 处理4月18日淘汰赛)
**文件**: [Frm设置第二步.cs 第196-259行](../../SJBS.Admin/比赛管理/Frm设置第二步.cs#L196-L259)
**方法**: `button8_Click()`
这是**最核心的方法**,完整流程如下:
#### 6.1 将内存列表写入数据库
```csharp
// 第207行
ResultMsg msg = new DALJibieRiqiSetList().Insert(lstLeftJibieRiqiSetList);
// 将 lstLeftJibieRiqiSetList 写入 JibieRiqiSetList 表
```
#### 6.2 按级别分组遍历
```csharp
// 第203-208行
var groupedByJibieId = this.lstLeftJibieRiqiSetList
    .GroupBy(x => x.JibieId)
    .Select(g => new { JibieId = g.Key, Items = g.ToList() })
    .ToList();
foreach (var group in groupedByJibieId)
{
    BisaiGongjiJi modelJibie = new DALBisaiGongjiJi().GetModel(group.JibieId);
    PressSetIn(modelJibie);  // &#9888;&#65039;&#9888;&#65039;&#9888;&#65039; 核心调用
    // ...
}
```
#### 6.3 PressSetIn → Processing_SingleDefeat(全量删除+重建)
**文件**: [Frm设置第二步.cs 第534行](../../SJBS.Admin/比赛管理/Frm设置第二步.cs#L534) → [第1433行](../../SJBS.Admin/比赛管理/Frm设置第二步.cs#L1433) → [第575行](../../SJBS.Admin/比赛管理/Frm设置第二步.cs#L575)
```
PressSetIn(modelJibie)
  └─ ChuliFangshiDanbaitaotaiAll(modelJibie, listXuanshou)
       └─ Processing_SingleDefeat(modelJibie, listXuanshou)  ← 核心方法
```
**Processing_SingleDefeat 方法** ([第575-900行](../../SJBS.Admin/比赛管理/Frm设置第二步.cs#L575-L900)):
```csharp
public ResultMsg Processing_SingleDefeat(BisaiGongjiJi ModelJB, List<XuanshouInfo> lstXuanshouInfo)
{
    // &#9888;&#65039;&#9888;&#65039;&#9888;&#65039; 第581-584行:先删除该级别的所有相关数据!!!
    new DALChangciInfo().DeleteByJibieId(ModelJB.Id);      // 删除所有场次
    new DALXuanshouCanshai().DeleteByJibieId(ModelJB.Id);   // 删除所有参数
    new DALDuizhanTu().DeleteByJibieId(ModelJB.Id);         // 删除所有对战图
    new DALXuanshouCanshaiRecord().DeleteByJibieId(ModelJB.Id);
    // 第一层循环:处理首轮(1/16决赛等最大列的数据)
    foreach (GudingBianpaiDuizhenBiao cur in lstMaxGudingBianpaiDuizhenBiao)
    {
        // 从 GudingBianpaiDuizhenBiao 固定编排表获取对阵信息
        // 从 BisaiGongjinjiBie 获取轮次结构(modelJBMx)
        // 从 JibieLunciRiqi 获取日期分配
        // 创建 ChangciInfo 并插入数据库
    }
    // 第二层循环:处理后续轮次(1/8, 1/4, 1/2, 决12)← 第710行
    for (int i = MaxLevelSet - 1; i >= 0; i--)  // 遍历所有列
    {
        // 同上,为每个固定编排项创建 ChangciInfo
    }
    // 第三部分:处理复活赛数据 ← 第897行
    foreach (BisaiGongjinjiBie ThisMx in ListJBMx.Where(x => x.ThisDuizhen < 0))
    {
        for (int i = 0; i < ThisMx.CangciCount; i++)
        {
            new DuizhanOp().AddNewDuizhan(HongX, LanX, ThisMx, InsertId, i + 1);
        }
    }
}
```
**&#9888;&#65039;&#9888;&#65039;&#9888;&#65039; 关键问题所在**:
- **每次调用 Processing_SingleDefeat 都会先 DeleteByJibieId 删除该级别所有数据**
- **然后基于 GudingBianpaiDuizhenBiao 固定编排表重建所有轮次的 ChangciInfo**
- **不管用户在"加入自动处理列表"中选择了哪些轮次,都会生成全部轮次**
#### 6.4 日期来源逻辑
**文件**: [Frm设置第二步.cs 第656-673行](../../SJBS.Admin/比赛管理/Frm设置第二步.cs#L656-L673)
```csharp
// 每个场次的日期获取方式:
string lunciType = GetLunciTypeByLunciName(redPlayer.Zhuangtai);
JibieLunciRiqi jibieLunciRiqi = new DALJibieLunciRiqi().GetByJibieAndType(ModelJB.Id, lunciType);
if (jibieLunciRiqi != null)
{
    ThisChangci.Riqi = jibieLunciRiqi.Riqi;     // 有分配就用分配的日期
}
else
{
    ThisChangci.Riqi = DateTime.Now.ToString("yyyy-MM-dd");  // &#9888;&#65039; 没有就用当天!
}
```
#### 6.5 生成对战图
**文件**: [DuizhantuCaozuoImageUpdate.cs 第25行](../../SJBSAdmin/对阵图/DuizhantuCaozuoImageUpdate.cs#L25)
**方法**: `InsertDuizhantuByDanBai()`
```csharp
public void InsertDuizhantuByDanBai(BisaiGongjiJi Jibie)
{
    new DALDuizhanTu().DeleteByJibieId(Jibie.Id);  // &#9888;&#65039; 又删一次!
    // 然后根据 ChangciInfo 重建 DuizhanTu
}
```
#### 6.6 更新场次编号
**文件**: [Frm设置第二步.cs 第245-259行](../../SJBS.Admin/比赛管理/Frm设置第二步.cs#L245-L259)
**方法**: `UpdateChangciNo()`
```csharp
private void UpdateChangciNo()
{
    int changciNo = 1;
    // &#9888;&#65039; 只遍历当前 lstLeftJibieRiqiSetList 中的项来编号
    foreach (JibieRiqiSetList cur in this.lstLeftJibieRiqiSetList)
    {
        List<ChangciInfo> lst = dal.GetListByJibieMxId(cur.JibieMxId);
        foreach (ChangciInfo ci in lst)
        {
            dal.UpdateChangciNo(ci.Id, changciNo++);  // 从1开始编号
        }
    }
}
```
---
### 步骤7:再次"加入自动处理列表"(选择4月19日的复活赛+决赛)
同步骤5,将4月19日的轮次追加到 `lstLeftJibieRiqiSetList` 内存列表中。
---
### 步骤8:再次"开始处理自动列表"(第二次 - 处理4月19日复活赛+决赛)
**&#9888;&#65039;&#9888;&#65039;&#9888;&#65039; 问题爆发点**
与步骤6完全相同的代码路径被执行:
```
button8_Click()
  ├─ Insert(lstLeftJibieRiqiSetList)          // 将新的 JibieRiqiSetList 写入DB
  └─ foreach 级别分组:
       └─ PressSetIn(modelJibie)               // &#9888;&#65039; 又调了一次!
            └─ Processing_SingleDefeat()        // &#9888;&#65039;&#9888;&#65039;&#9888;&#65039; 又删又建!
                 ├─ DeleteByJibieId()           // 删除该级别所有数据(包括步骤6已正确生成的!)
                 └─ 重新生成所有轮次...           // 基于固定编排表全量重建
```
---
## 四、问题描述
### 用户操作
1. 单复活模式下完成抽签
2. 点击"生成全部场次数据"
3. 设置4月18日(淘汰赛)、4月19日(复活赛+决赛)
4. **第一次**"开始处理自动列表":只选4月18日淘汰赛 → &#9989; 正常
5. **第二次**"开始处理自动列表":只选4月19日复活赛+决赛 → &#10060; 出错
### 错误现象
- 4月18日数据不完整:淘汰赛只有1/8,缺少1/4和1/2
- 4月19日出现重复/错乱数据:混入了其他级别的淘汰赛
- 场次编号混乱
---
## 五、需要展示给其他程序员的关键代码清单
按阅读顺序排列:
### &#128308; 必看(核心问题所在)
| 序号 | 文件 | 行号 | 方法/代码 | 说明 |
|------|------|------|-----------|------|
| 1 | `Frm设置第二步.cs` | **196-259** | `button8_Click()` | **入口方法,整个处理流程的起点** |
| 2 | `Frm设置第二步.cs` | **575-584** | `Processing_SingleDefeat()` 开头 | **&#9888;&#65039; 先Delete再重建的逻辑** |
| 3 | `Frm设置第二步.cs` | **710行附近** | `for (int i = MaxLevelSet - 1; i >= 0; i--)` | **第二层循环:生成所有后续轮次(不管用户选了什么)** |
| 4 | `Frm设置第二步.cs` | **656-673** | 日期获取逻辑 | **没有日期分配时用 DateTime.Now** |
### &#128993; 重要(理解数据流)
| 序号 | 文件 | 行号 | 方法/代码 | 说明 |
|------|------|------|-----------|------|
| 5 | `Frm单复活抽签.cs` | **1094-1143** | `CreateChangci()` | **"生成全部场次数据"按钮:清空+重建轮次结构** |
| 6 | `DALBisaiGongjinjiBie.cs` | **55-88** | `CleanTheJibieMx()` | **清空SQL:删除7张表的级联清理** |
| 7 | `Frm设置第二步.cs` | **283-391** | `button1_Click()` | **"加入自动处理列表":只写内存,不写DB** |
| 8 | `Frm设置第二步.cs` | **534-563** | `PressSetIn()` | **调度方法:根据赛制分发到不同处理函数** |
| 9 | `Frm设置第二步.cs` | **1433-1447** | `ChuliFangshiDanbaitaotaiAll()` | **单败淘汰入口,直接调用 Processing_SingleDefeat** |
| 10 | `DuizhantuCaozuoImageUpdate.cs` | **25-30** | `InsertDuizhantuByDanBai()` 开头 | **对战图生成:也是先Delete再重建** |
| 11 | `Frm设置第二步.cs` | **245-259** | `UpdateChangciNo()` | **场次编号:只对当前列表编号,不是全局重编** |
### &#128994; 辅助(理解数据模型)
| 序号 | 文件 | 行号 | 说明 |
|------|------|------|------|
| 12 | `JibieRiqiSetList.cs` | 全文 | **JibieRiqiSetList 实体类定义**(字段说明) |
| 13 | `SJBSHelper.cs` | **370-588** | `ProcessSingleElimination()` | **轮次结构生成算法(生成 BisaiGongjinjiBie)** |
---
## 六、数据流时序图
```
时间线 →
【用户】                    【代码执行】                          【数据库变化】
                                                                                    
抽签 ──────────────────> Frm单复活抽签                        XuanshouInfo(签号)
                           │
"生成全部场次数据" ──────> CreateChangci()
                           ├─ DeleteAll(JibieLunciRiqi)         清空日期分配
                           ├─ CleanTheJibieMx(每个级别)           清空7张表 &#9888;&#65039;
                           └─ ProcessSingleElimination()         生成 BisaiGongjinjiBie
                                                                (只有轮次结构,无场次)
                           │
"设置日期"(第一步) ───────> 用户界面操作                         写入 JibieLunciRiqi
                           │
"第二步更新" ────────────> 界面刷新                              无DB操作
                           │
"加入自动处理列表" ───────> button1_Click()
                           │                                    写入 lstLeft 内存列表
                           │                                    (无DB操作)
                           │
"开始处理自动列表"(第1次) ─> button8_Click()  ←─────────────── 4月18日淘汰赛
                           │
                           ├─ Insert(lstLeft)                   写入 JibieRiqiSetList
                           │
                           ├─ PressSetIn(男自55kg)
                           │  └─ Processing_SingleDefeat()
                           │     ├─ DeleteByJibieId(55kg)      &#9888;&#65039; 删除55kg所有数据
                           │     ├─ 循环生成 1/16 决赛场次      ChangciInfo(日期=4/18)
                           │     ├─ 循环生成 1/8 决赛场次       ChangciInfo(日期=4/18)
                           │     ├─ 循环生成 1/4 决赛场次       ChangciInfo(日期=4/18)
                           │     ├─ 循环生成 1/2 决赛场次       ChangciInfo(日期=4/18)
                           │     ├─ 循环生成 决12 场次          ChangciInfo(日期=4/18)
                           │     └─ 循环生成 复活赛 场次         ChangciInfo(日期=??)
                           │
                           ├─ InsertDuizhantuByDanBai()        重建 DuizhanTu
                           │
                           └─ UpdateChangciNo()                 编号 1~N
                           │
                           │                                    &#9989; 数据正常
                           │
"加入自动处理列表"(第2次)> button1_Click()
                           │                                    追加到 lstLeft 内存列表
                           │                                    (含4/19复活赛项)
                           │
"开始处理自动列表"(第2次) ─> button8_Click()  ←─────────────── 4月19日复活赛
                           │
                           ├─ Insert(lstLeft)                   追加写入 JibieRiqiSetList
                           │
                           ├─ PressSetIn(男自55kg)              &#9888;&#65039;&#9888;&#65039;&#9888;&#65039; 又执行了!
                           │  └─ Processing_SingleDefeat()
                           │     ├─ DeleteByJibieId(55kg)      &#9888;&#65039;&#9888;&#65039;&#9888;&#65039; 删除55kg所有数据
                           │     │                             包括刚才正确生成的4/18数据!
                           │     ├─ 循环生成 所有轮次...
                           │     │  日期来源: JibieLunciRiqi
                           │     │  如果某轮次没日期分配 → DateTime.Now=4/19 &#10060;
                           │     │
                           │     └─ 结果: 4/18数据丢失 + 4/19数据错乱
                           │
                           ├─ InsertDuizhantuByDanBai()        又删又建 DuizhanTu
                           │
                           └─ UpdateChangciNo()                 只对新列表项编号
                                                                &#10060; 数据错乱
```
---
## 七、问题的精确描述(供其他程序员参考)
### 现象
当同一个级别(如男自55kg)的场次被分两次处理(先处理4月18日淘汰赛,再处理4月19日复活赛)时,第二次处理会破坏第一次已生成的数据。
### 根因
`button8_Click` 方法中对每个级别都会无条件调用 `PressSetIn``Processing_SingleDefeat`,而 `Processing_SingleDefeat` 的设计是**全量删除+全量重建**(DeleteByJibieId + 全轮次循环生成)。这意味着:
1. 第一次处理:生成所有轮次(包括不该在这天处理的复活赛),但日期可能不对
2. 第二次处理:**删除第一次的所有数据**(包括正确的淘汰赛数据),然后重新生成所有轮次
3. 第二次生成时,某些轮次可能因缺少 `JibieLunciRiqi` 日期分配而使用默认日期(DateTime.Now)
### 涉及的关键设计决策
- `Processing_SingleDefeat` 是为**一次性全量生成**设计的,不支持增量/分批处理
- `button8_Click` 不检查该级别是否已有数据,每次都走全量重建路径
- 日期回退机制(`DateTime.Now`)在分批处理场景下会导致跨日污染
- `UpdateChangciNo` 只对当前处理的列表项编号,不考虑数据库中已有的其他场次以前的赛制是如4月18日完成单败淘汰的男自55kg淘汰赛(1/16、1/8、1/4、1/2)和复活赛(复1、复2)决赛(决3-5、决1-2),碰到1/2的胜利方的都进行复活赛,这些赛制都是写好的。但是现在如男自55kg要在4月18日完成淘汰赛,4月19日完成复活赛和决赛,还要保持原来的复活和决赛产生的关系但是现在我用ai改的全部都是错乱的数据求解决思路,奖给第一人

吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
 楼主| cxq97241916 发表于 2026-4-18 19:55 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

警告:本站严惩灌水回复,尊重自己从尊重他人开始!

1层
2层

免责声明

吾爱汇编(www.52hb.com)所讨论的技术及相关工具仅限用于研究学习,皆在提高软件产品的安全性,严禁用于不良动机。任何个人、团体、组织不得将其用于非法目的,否则,一切后果自行承担。吾爱汇编不承担任何因为技术滥用所产生的连带责任。吾爱汇编内容源于网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除。如有侵权请邮件或微信与我们联系处理。

站长邮箱:SharkHeng@sina.com
站长QQ:1140549900


QQ|RSS|手机版|小黑屋|帮助|吾爱汇编 ( 京公网安备11011502005403号 , 京ICP备20003498号-6 )|网站地图

Powered by Discuz!

吾爱汇编 www.52hb.com

快速回复 返回顶部 返回列表