Skip to content

Commit 1a5b7de

Browse files
authored
Merge pull request #435 from CnCNet/develop
Develop
2 parents f3a52ff + f73016e commit 1a5b7de

File tree

3 files changed

+137
-8
lines changed

3 files changed

+137
-8
lines changed

cncnet-api/app/Http/Services/QuickMatchService.php

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -633,14 +633,17 @@ public function createQmAIMatch($qmPlayer, $userPlayerTier, $maps, $gameType)
633633

634634
$qmPlayer->save();
635635

636-
$perMS = array_values(array_filter($qmMap->sides_array(), function ($s)
636+
$mapSides = array_values(array_filter($qmMap->sides_array(), fn($s) => $s >= 0));
637+
$ladderSides = $qmMatch->ladder->qmLadderRules->all_sides();
638+
$allowedForRandom = array_values(array_intersect($mapSides, $ladderSides));
639+
if (empty($allowedForRandom))
637640
{
638-
return $s >= 0;
639-
}));
641+
$allowedForRandom = $mapSides;
642+
}
640643

641644
if ($qmPlayer->actual_side == -1)
642645
{
643-
$qmPlayer->actual_side = $perMS[mt_rand(0, count($perMS) - 1)];
646+
$qmPlayer->actual_side = $allowedForRandom[mt_rand(0, count($allowedForRandom) - 1)];
644647
}
645648
$qmPlayer->save();
646649

@@ -1102,10 +1105,19 @@ public function createQmMatch(
11021105
}
11031106
$qmPlayerFresh->save();
11041107

1105-
$perMS = array_values(array_filter($qmMap->sides_array(), function ($s)
1108+
$mapSides = array_values(array_filter($qmMap->sides_array(), function ($s)
11061109
{
11071110
return $s >= 0;
11081111
}));
1112+
$ladderSides = $ladder->qmLadderRules->all_sides();
1113+
$perMS = array_values(array_intersect($mapSides, $ladderSides));
1114+
1115+
if (empty($perMS))
1116+
{
1117+
// Fallback: if intersection of map sides and allowed ladder sides is empty, use map sides.
1118+
Log::warning('No intersection between map sides and ladder sides');
1119+
$perMS = $mapSides;
1120+
}
11091121

11101122
if ($qmPlayerFresh->isObserver() == true)
11111123
{
@@ -1239,7 +1251,15 @@ private function setTeamSpawns(string $team, string $spawnOrders, Collection $te
12391251

12401252
Log::debug('[QuickMatchService::setTeamSpawns] $spawnOrder ' . json_encode($spawnOrder));
12411253

1242-
$mapAllowedSides = array_values(array_filter($qmMap->sides_array(), fn($s) => $s >= 0));
1254+
$mapSides = array_values(array_filter($qmMap->sides_array(), fn($s) => $s >= 0));
1255+
$ladderSides = $qmMatch->ladder->qmLadderRules->all_sides();
1256+
$allowedForRandom = array_values(array_intersect($mapSides, $ladderSides));
1257+
if (empty($allowedForRandom))
1258+
{
1259+
// Fallback: if intersection of map sides and allowed ladder sides is empty, use map sides.
1260+
Log::warning('No intersection between map sides and ladder sides');
1261+
$allowedForRandom = $mapSides;
1262+
}
12431263

12441264
foreach ($teamPlayers->values() as $i => $player)
12451265
{
@@ -1267,7 +1287,7 @@ private function setTeamSpawns(string $team, string $spawnOrders, Collection $te
12671287

12681288
if ($qmPlayer->actual_side == -1)
12691289
{
1270-
$qmPlayer->actual_side = $mapAllowedSides[mt_rand(0, count($mapAllowedSides) - 1)];
1290+
$qmPlayer->actual_side = $allowedForRandom[mt_rand(0, count($allowedForRandom) - 1)];
12711291
}
12721292

12731293
$qmPlayer->qm_match_id = $qmMatch->id;

cncnet-api/app/Models/QmLadderRules.php

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,28 @@ public function mapPools()
7474

7575
public function all_sides()
7676
{
77-
return explode(',', $this->id ? $this->all_sides : "");
77+
$raw = $this->id ? (string) $this->all_sides : '';
78+
79+
if (trim($raw) === '')
80+
{
81+
return [];
82+
}
83+
84+
$parts = explode(',', $raw);
85+
$result = [];
86+
87+
// Make sure to get an int array.
88+
foreach ($parts as $p)
89+
{
90+
$p = trim($p);
91+
if ($p === '')
92+
{
93+
continue; // Do not cast an empty part to 0.
94+
}
95+
$result[] = (int) $p;
96+
}
97+
98+
return $result;
7899
}
79100

80101
public function allowed_sides()
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*/
12+
public function up(): void
13+
{
14+
Schema::table('players', function (Blueprint $table) {
15+
// Optimize findMatch() - called via /api/v2/qm/{ladder}/{playerName}
16+
$table->index(['ladder_id', 'username'], 'idx_players_ladder_username');
17+
// Optimize lookups by user_id (used in multiple services)
18+
$table->index('user_id', 'idx_players_user_id');
19+
});
20+
21+
Schema::table('users', function (Blueprint $table) {
22+
// Optimize checkUserForBans(), used every time findMatch() is called
23+
$table->index('ip_address_id', 'idx_users_ip_address_id');
24+
$table->index('primary_user_id', 'idx_users_primary_user_id');
25+
});
26+
27+
Schema::table('game_reports', function (Blueprint $table) {
28+
// Optimize StatsService calls: getWinnerOfTheDay, getPlayerOfTheDay, getFactionsPlayedByPlayer
29+
$table->index(['valid', 'best_report', 'created_at'], 'idx_game_reports_valid_best_created');
30+
});
31+
32+
Schema::table('qm_match_players', function (Blueprint $table) {
33+
// Optimize queries checking if a player is waiting in queue
34+
$table->index(['player_id', 'waiting'], 'idx_qm_match_players_player_waiting');
35+
});
36+
37+
Schema::table('ip_addresses', function (Blueprint $table) {
38+
// Optimize lookups by IP address (used for bans / login checks)
39+
$table->index('address', 'idx_ip_addresses_address');
40+
});
41+
42+
Schema::table('player_active_handles', function (Blueprint $table) {
43+
// Optimize getPlayerActiveHandle(), used in username-based API calls
44+
$table->index(['player_id', 'ladder_id', 'created_at'], 'idx_pah_player_ladder_created');
45+
});
46+
47+
Schema::table('bans', function (Blueprint $table) {
48+
// Optimize ban lookups by user + expiration date
49+
$table->index(['user_id', 'expires'], 'idx_bans_user_expires');
50+
});
51+
}
52+
53+
/**
54+
* Reverse the migrations.
55+
*/
56+
public function down(): void
57+
{
58+
Schema::table('players', function (Blueprint $table) {
59+
$table->dropIndex('idx_players_ladder_username');
60+
$table->dropIndex('idx_players_user_id');
61+
});
62+
63+
Schema::table('users', function (Blueprint $table) {
64+
$table->dropIndex('idx_users_ip_address_id');
65+
$table->dropIndex('idx_users_primary_user_id');
66+
});
67+
68+
Schema::table('game_reports', function (Blueprint $table) {
69+
$table->dropIndex('idx_game_reports_valid_best_created');
70+
});
71+
72+
Schema::table('qm_match_players', function (Blueprint $table) {
73+
$table->dropIndex('idx_qm_match_players_player_waiting');
74+
});
75+
76+
Schema::table('ip_addresses', function (Blueprint $table) {
77+
$table->dropIndex('idx_ip_addresses_address');
78+
});
79+
80+
Schema::table('player_active_handles', function (Blueprint $table) {
81+
$table->dropIndex('idx_pah_player_ladder_created');
82+
});
83+
84+
Schema::table('bans', function (Blueprint $table) {
85+
$table->dropIndex('idx_bans_user_expires');
86+
});
87+
}
88+
};

0 commit comments

Comments
 (0)