feat(游戏模块): 重构比赛逻辑并添加赛制支持

- 移除了原有的比赛时间检查逻辑
- 引入了赛制类文件,实现了比赛自动编排功能
- 新增了 GameMatch 模型用于存储比赛对阵信息
- 优化了数据库事务处理逻辑
- 更新了 Composer 自动加载配置,添加 format 命名空间
This commit is contained in:
2025-05-23 17:37:48 +08:00
parent 8481d8ef0c
commit ac0777e34b
9 changed files with 140 additions and 4593 deletions

View File

@@ -8,12 +8,14 @@ use app\admin\model\zy\Club;
use app\admin\model\zy\Stadium; use app\admin\model\zy\Stadium;
use think\exception\PDOException; use think\exception\PDOException;
use app\admin\model\zy\game\GameJoin; use app\admin\model\zy\game\GameJoin;
use app\admin\model\zy\game\GameMatch;
use think\exception\ValidateException; use think\exception\ValidateException;
use app\admin\model\zy\game\Participant; use app\admin\model\zy\game\Participant;
class Game extends Base class Game extends Base
{ {
public function __construct() public function __construct()
{ {
$this->model = new \app\admin\model\zy\game\Game; $this->model = new \app\admin\model\zy\game\Game;
@@ -84,15 +86,15 @@ class Game extends Base
if (empty($game)) { if (empty($game)) {
$this->error('比赛不存在'); $this->error('比赛不存在');
} }
$dataTime = date('Y-m-d H:i:s'); // $dataTime = date('Y-m-d H:i:s');
$startTime = $game['date'] . ' ' . $game['start_time']; // $startTime = $game['date'] . ' ' . $game['start_time'];
if ($dataTime < $startTime) { // if ($dataTime < $startTime) {
$this->error('比赛时间未开始'); // $this->error('比赛时间未开始');
} // }
$endTime = $game['date'] . ' ' . $game['end_time']; // $endTime = $game['date'] . ' ' . $game['end_time'];
if ($dataTime > $endTime) { // if ($dataTime > $endTime) {
$this->error('比赛时间已结束'); // $this->error('比赛时间已结束');
} // }
$participant = Participant::where('game_id', $game['id'])->where('status', 1)->select(); $participant = Participant::where('game_id', $game['id'])->where('status', 1)->select();
if (empty($participant)) { if (empty($participant)) {
$join = GameJoin::where('game_id', $game['id'])->where('status', 1)->select(); $join = GameJoin::where('game_id', $game['id'])->where('status', 1)->select();
@@ -114,48 +116,26 @@ class Game extends Base
$order++; $order++;
} }
} }
$this->model->saveAll($participant); $this->model->allowField(true)->save($participant);
} }
if ($game['team_type'] == 1) { //双打 $gameClass = 'format\\Game' . $game['team_type'] . $game['rule_type'];
// 转转 4-16 每个人与其他人各搭档1次决出个人排名 人数 4 ≦ n ≦ 16 (Default8) if (!class_exists($gameClass)) {
// 轮数 3 ≦ mn (Default7) 报名费 0 ≦ m ≦ 10 元 (Default: 5) throw new Exception("赛制文件不存在,请联系管理人员: {$gameClass}");
// 由前几名按比例瓜分 (可调 Default40%/30%/20%/10%)
// 混双转 4-32
// (偶数) 每男与每女各搭档1次分别决出男女排名 人数 4 ≦ n ≦ 32 (Default16)
// 轮数2 ≦ m ≦ n/2 (Default8) 报名费 0 ≦ m ≦ 10 元 (Default: 5)
// 由前几名按比例瓜分 (可调 Default40%/30%/20%/10%)
// 固搭转 4-32
// (偶数) 固定组合,分别与其他组合对战一次,决出组合排名 人数 4 ≦ n ≦ 32 (Default16)
// 轮数 2 ≦ m ≦ n/2-1 (Default7) 报名费 0 ≦ m ≦ 10 元 (Default: 5)
// 由前几名按比例瓜分 (可调 Default40%/30%/20%/10%)
// 分区转 4-32
// (偶数) 分为AB两区A区与B区各搭档1次分别决出AB区排名 人数 4 ≦ n ≦ 32 (Default16)
// 轮数2 ≦ m ≦ n/2 (Default8) 报名费 0 ≦ m ≦ 10 元 (Default: 5)
// 由前几名按比例瓜分 (可调 Default40%/30%/20%/10%)
// 擂台赛 8-44 由擂主决定出战组合,攻擂者按组合报名(不重复报名,但可兼项) 擂主人数 2 ≦ k ≦ 4 (Default2)
// 总攻擂数4 ≦ n ≦ 5k(Default8) 攻擂报名费 0 ≦ m ≦ 10 (Default5)
// 擂主报名费 2n/k (不可调)
// 攻擂者赢局获得2m元(不可调)
// 由擂主分摊盈亏
// 守擂赛 4-32
// (偶数) 选手组合报名不可重复报名抽签决定对战顺序相邻顺序对战连赢m局进入决赛决赛为淘汰赛决出冠亚季 人数 4 ≦ n ≦ 32 (Default16)
// 连赢 1 ≦ m ≦ 3 (Default2) 报名费0 ≦ k ≦ 10 (Default5)
// 由前几名按比例瓜分 (可调 Default40%/30%/20%/10%)
if ($game['rule_type'] == 1) { //转转
foreach ($participant as $key => $value) {
} }
$format = new $gameClass;
if (!$format instanceof \format\GameInterface) {
throw new Exception("赛制配置错误,请联系管理人员: {$gameClass}");
} }
} elseif ($game['team_type'] == 2) { //单打 $matchs = $format->match($game, $participant);
$res = (new GameMatch)->insertAll($matchs);
} elseif ($game['team_type'] == 3) { //团队
}
Db::commit(); Db::commit();
} catch (ValidateException | PDOException | Exception $e) { } catch (ValidateException | PDOException | Exception $e) {
Db::rollback(); Db::rollback();
$this->error($e->getMessage(), $e); $this->error($e->getMessage(), $e);
} }
// print_r($res);
$this->success('Success', ['list' => $participant]); $this->success('Success', $res);
} }
} }

View File

@@ -41,7 +41,8 @@
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"addons\\": "addons/" "addons\\": "addons/",
"format\\": "format/"
} }
}, },
"repositories": [ "repositories": [

72
format/Game17.php Normal file
View File

@@ -0,0 +1,72 @@
<?php
namespace format;
class Game17 implements GameInterface
{
// 赛制说明
public function describe(): string
{
return '双打+八人转 比赛说明:
每个人与其他人各搭档1次决出个人排名
数 4 ≦ n ≦ 16 (Default8)
轮数 3 ≦ mn (Default7)
报名费 0 ≦ m ≦ 10 元 (Default: 5)
由前几名按比例瓜分 (可调 Default40%/30%/20%/10%)';
}
// 对阵安排
public function match($game, $users): array
{
$math = $team = [];
$utotal = count($users);
for ($i = 0; $i < $utotal; $i++) {
for ($j = $i + 1; $j < $utotal; $j++) {
$team[] = json_encode([
'name' => 'team' . $i . $j,
'user' => [
[
'user_id' => $users[$i]['user_id'],
'gender' => $users[$i]['gender'],
'avatar' => $users[$i]['avatar'],
'name' => $users[$i]['name'],
],
[
'user_id' => $users[$j]['user_id'],
'gender' => $users[$j]['gender'],
'avatar' => $users[$j]['avatar'],
'name' => $users[$j]['name'],
]
]
]);
}
}
// dd($team);
$ttotal = count($users);
$n = 1;
for ($i = 0; $i < $ttotal; $i++) {
for ($j = $i + 1; $j < $ttotal; $j++) {
$math[] = [
'gym_id' => $game['gym_id'],
'club_id' => $game['club_id'],
'act_id' => $game['act_id'],
'game_id' => $game['id'],
'level' => 1,
'turn' => $n,
'teamA' => $team[$i],
'teamB' => $team[$j],
];
$n++;
}
}
// dd($math);
return $math;
}
// 奖金分配
public function prize($rank): array
{
return $rank;
}
}

24
format/GameInterface.php Normal file
View File

@@ -0,0 +1,24 @@
<?php
namespace format;
/*
赛制文件
1. 团队类型1双打2单打3团队
2. 规则类型1八人转2超八转3混双转4固搭转5固定擂6活动擂7转转8分区转9擂台赛10守擂赛11追分赛12固搭追分赛13大循环群内赛14两队PK赛15战队淘汰赛16单项淘汰赛17分区循环淘汰赛
3. 需要引入新赛制请创建新的类文件,类文件需要实现GameInterface接口,并且文件名为`Game + 团队类型代码 + 规则类型代码.php`。
如:赛制为双打八人转则文件为format/Game11.php。
赛制为单打擂台赛则文件为format/Game29.php。
*/
interface GameInterface
{
// 赛制说明
public function describe(): string;
// 对阵安排
public function match($game,$users): array;
// 奖金分配
public function prize($rank): array;
}

5
vendor/autoload.php vendored
View File

@@ -14,7 +14,10 @@ if (PHP_VERSION_ID < 50600) {
echo $err; echo $err;
} }
} }
throw new RuntimeException($err); trigger_error(
$err,
E_USER_ERROR
);
} }
require_once __DIR__ . '/composer/autoload_real.php'; require_once __DIR__ . '/composer/autoload_real.php';

View File

@@ -1,4 +1,3 @@
Copyright (c) Nils Adermann, Jordi Boggiano Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -18,4 +17,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,8 @@ return array(
'think\\helper\\' => array($vendorDir . '/topthink/think-helper/src'), 'think\\helper\\' => array($vendorDir . '/topthink/think-helper/src'),
'think\\composer\\' => array($vendorDir . '/topthink/think-installer/src'), 'think\\composer\\' => array($vendorDir . '/topthink/think-installer/src'),
'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'), 'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'),
'think\\' => array($vendorDir . '/topthink/think-queue/src', $vendorDir . '/fastadminnet/fastadmin-addons/src', $baseDir . '/thinkphp/library/think'), 'think\\' => array($vendorDir . '/fastadminnet/fastadmin-addons/src', $baseDir . '/thinkphp/library/think', $vendorDir . '/topthink/think-queue/src'),
'format\\' => array($baseDir . '/format'),
'addons\\' => array($baseDir . '/addons'), 'addons\\' => array($baseDir . '/addons'),
'ZipStream\\' => array($vendorDir . '/maennchen/zipstream-php/src'), 'ZipStream\\' => array($vendorDir . '/maennchen/zipstream-php/src'),
'Workerman\\' => array($vendorDir . '/workerman/workerman'), 'Workerman\\' => array($vendorDir . '/workerman/workerman'),

File diff suppressed because it is too large Load Diff