Skip to content

Commit

Permalink
Merge pull request #2696 from RaiderIO/development
Browse files Browse the repository at this point in the history
Release v11.9.6 - Final heatmap push
  • Loading branch information
Wotuu authored Jan 31, 2025
2 parents 11d7fec + 7e21ce8 commit 8994a86
Show file tree
Hide file tree
Showing 32 changed files with 389 additions and 89 deletions.
4 changes: 4 additions & 0 deletions app/Http/Requests/Heatmap/AjaxGetDataFormRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Http\Requests\Heatmap;

use App\Models\Affix;
use App\Models\CharacterClassSpecialization;
use App\Models\Dungeon;
use Illuminate\Validation\Rule;

Expand All @@ -29,6 +30,9 @@ public function rules(): array
// These are overrides since it's easier to split the csv as an array for this endpoint
'includeAffixIds' => ['nullable', 'array'],
'includeAffixIds.*' => ['integer', Rule::exists(Affix::class, 'affix_id')],
// These are overrides since it's easier to split the csv as an array for this endpoint
'includeSpecIds' => ['nullable', 'array'],
'includeSpecIds.*' => ['integer', Rule::exists(CharacterClassSpecialization::class, 'specialization_id')],
]);
}
}
Expand Down
3 changes: 2 additions & 1 deletion app/Http/Requests/Heatmap/ExploreUrlFormRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ public function rules(): array
'maxItemLevel' => ['nullable', 'integer'],
'minPlayerDeaths' => ['nullable', 'integer'],
'maxPlayerDeaths' => ['nullable', 'integer'],
'includeAffixIds' => ['nullable', 'string'],
'includeAffixIds' => ['nullable', 'string'], // csv
'includeSpecIds' => ['nullable', 'string'], // csv
'minPeriod' => ['nullable', 'integer'],
'maxPeriod' => ['nullable', 'integer'],
'minTimerFraction' => ['nullable', 'numeric'],
Expand Down
2 changes: 2 additions & 0 deletions app/Logic/MapContext/MapContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use App\Http\Controllers\Traits\ListsEnemies;
use App\Models\CharacterClass;
use App\Models\CharacterClassSpecialization;
use App\Models\Dungeon;
use App\Models\Faction;
use App\Models\Floor\Floor;
Expand Down Expand Up @@ -117,6 +118,7 @@ function () use ($mapFacadeStyle) {
'unknownMapIconType' => MapIconType::find(MapIconType::ALL[MapIconType::MAP_ICON_TYPE_UNKNOWN]),
'awakenedObeliskGatewayMapIconType' => MapIconType::find(MapIconType::ALL[MapIconType::MAP_ICON_TYPE_GATEWAY]),
'classColors' => CharacterClass::all()->pluck('color'),
'characterClassSpecializations' => CharacterClassSpecialization::all(),
'raidMarkers' => RaidMarker::all(),
'factions' => Faction::where('name', '<>', 'Unspecified')->with('iconfile')->get(),
'publishStates' => PublishedState::all(),
Expand Down
2 changes: 1 addition & 1 deletion app/Models/GameServerRegion.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,6 @@ public function getRegionEpochByDate(Carbon $dateTime): ?Carbon
return Carbon::parse(self::EU_EPOCH_CHANGE_DATE);
}

return $this->epoch_start;
return Carbon::parse($this->epoch_start);
}
}
4 changes: 3 additions & 1 deletion app/Providers/KeystoneGuruServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -493,12 +493,14 @@ static function (View $view) use ($globalViewVariables) {
});

// Maps
view()->composer('common.maps.controls.heatmapsearch', static function (View $view) use ($viewService, &$userOrDefaultRegion) {
view()->composer('common.maps.controls.heatmapsearch', static function (View $view) use ($viewService, $globalViewVariables, &$userOrDefaultRegion) {
$userOrDefaultRegion ??= GameServerRegion::getUserOrDefaultRegion();
$regionViewVariables = $viewService->getGameServerRegionViewVariables($userOrDefaultRegion);
$view->with('showAllEnabled', $_COOKIE['dungeon_speedrun_required_npcs_show_all'] ?? '0');
$view->with('allAffixGroupsByActiveExpansion', $regionViewVariables['allAffixGroupsByActiveExpansion']);
$view->with('featuredAffixesByActiveExpansion', $regionViewVariables['featuredAffixesByActiveExpansion']);

$view->with('characterClassSpecializations', $globalViewVariables['characterClassSpecializations']);
});
view()->composer('common.maps.controls.pulls', static function (View $view) {
$view->with('showAllEnabled', $_COOKIE['dungeon_speedrun_required_npcs_show_all'] ?? '0');
Expand Down
41 changes: 40 additions & 1 deletion app/Service/CombatLogEvent/Dtos/CombatLogEventFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Service\CombatLogEvent\Dtos;

use App\Models\Affix;
use App\Models\CharacterClassSpecialization;
use App\Models\CombatLog\CombatLogEventDataType;
use App\Models\CombatLog\CombatLogEventEventType;
use App\Models\Dungeon;
Expand Down Expand Up @@ -33,6 +34,9 @@ class CombatLogEventFilter implements Arrayable

/** @var Collection<Affix> */
private Collection $affixes;

/** @var Collection<CharacterClassSpecialization> */
private Collection $specializations;
private ?int $periodMin = null;
private ?int $periodMax = null;
private ?int $durationMin = null;
Expand All @@ -44,7 +48,8 @@ public function __construct(
private readonly CombatLogEventEventType $eventType,
private readonly CombatLogEventDataType $dataType
) {
$this->affixes = collect();
$this->affixes = collect();
$this->specializations = collect();
}

public function getDungeon(): Dungeon
Expand Down Expand Up @@ -153,6 +158,25 @@ public function setAffixes(Collection $affixes): CombatLogEventFilter
return $this;
}

/**
* @return Collection<CharacterClassSpecialization>
*/
public function getSpecializations(): Collection
{
return $this->specializations;
}

/**
* @param Collection<CharacterClassSpecialization> $specializations
* @return CombatLogEventFilter
*/
public function setSpecializations(Collection $specializations): CombatLogEventFilter
{
$this->specializations = $specializations;

return $this;
}

public function getPeriodMin(): ?int
{
return $this->periodMin;
Expand Down Expand Up @@ -212,6 +236,9 @@ public function toArray(): array
'affixes' => $this->affixes->map(function (Affix $affix) {
return __($affix->name, [], 'en_US');
}),
'specializations' => $this->specializations->map(function (CharacterClassSpecialization $characterClassSpecialization) {
return __($characterClassSpecialization->name, [], 'en_US');
}),
'period_min' => $this->periodMin,
'period_max' => $this->periodMax,
'duration_min' => $this->durationMin,
Expand Down Expand Up @@ -283,6 +310,17 @@ public function toOpensearchQuery(array $must = []): array
]);
}

// @TODO Add nested query for specializations - it's nested in the character data
// if ($this->specializations->isNotEmpty()) {
// $must[] = BoolQuery::make([
// Should::make(
// $this->specializations->map(function (CharacterClassSpecialization $characterClassSpecialization) {
// return MatchOne::make('spec_id', $characterClassSpecialization->specialization_id);
// })->toArray()
// ),
// ]);
// }

// Add an AffixGroup filter
$mostRecentSeason = $this->seasonService->getMostRecentSeasonForDungeon($dungeon);

Expand Down Expand Up @@ -336,6 +374,7 @@ public static function fromHeatmapDataFilter(SeasonServiceInterface $seasonServi
$combatLogEventFilter->setPlayerDeathsMin($heatmapDataFilter->getPlayerDeathsMin());
$combatLogEventFilter->setPlayerDeathsMax($heatmapDataFilter->getPlayerDeathsMax());
$combatLogEventFilter->setAffixes($heatmapDataFilter->getIncludeAffixIds());
$combatLogEventFilter->setSpecializations($heatmapDataFilter->getIncludeSpecIds());
$combatLogEventFilter->setPeriodMin($heatmapDataFilter->getMinPeriod());
$combatLogEventFilter->setPeriodMax($heatmapDataFilter->getMaxPeriod());

Expand Down
42 changes: 41 additions & 1 deletion app/Service/RaiderIO/Dtos/HeatmapDataFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@


use App\Models\Affix;
use App\Models\CharacterClassSpecialization;
use App\Models\CombatLog\CombatLogEventDataType;
use App\Models\CombatLog\CombatLogEventEventType;
use App\Models\Dungeon;
Expand All @@ -25,6 +26,8 @@ class HeatmapDataFilter implements Arrayable
private ?int $playerDeathsMax = null;
/** @var Collection<Affix> */
private Collection $includeAffixIds;
/** @var Collection<CharacterClassSpecialization> */
private Collection $includeSpecIds;
private ?int $minPeriod = null;
private ?int $maxPeriod = null;
private ?int $timerFractionMin = null;
Expand All @@ -36,6 +39,7 @@ public function __construct(
private readonly CombatLogEventDataType $dataType
) {
$this->includeAffixIds = collect();
$this->includeSpecIds = collect();
}

public function getDungeon(): Dungeon
Expand Down Expand Up @@ -144,6 +148,25 @@ public function setIncludeAffixIds(Collection $includeAffixIds): HeatmapDataFilt
return $this;
}

/**
* @return Collection<CharacterClassSpecialization>
*/
public function getIncludeSpecIds(): Collection
{
return $this->includeSpecIds;
}

/**
* @param Collection<CharacterClassSpecialization> $includeSpecIds
* @return HeatmapDataFilter
*/
public function setIncludeSpecIds(Collection $includeSpecIds): HeatmapDataFilter
{
$this->includeSpecIds = $includeSpecIds;

return $this;
}

public function getMinPeriod(): ?int
{
return $this->minPeriod;
Expand Down Expand Up @@ -188,6 +211,12 @@ public function setTimerFractionMax(?int $timerFractionMAx): HeatmapDataFilter
return $this;
}

/**
* Converts the filter into an array that will be passed to the Raider.io API in the URL
*
* @param Season|null $mostRecentSeason
* @return array
*/
public function toArray(Season $mostRecentSeason = null): array
{
$result = [
Expand All @@ -206,7 +235,15 @@ public function toArray(Season $mostRecentSeason = null): array
$result['maxTimerFraction'] = $this->getTimerFractionMax();

if ($this->getIncludeAffixIds()->isNotEmpty()) {
$result['includeAffixIds'] = implode(',', $this->getIncludeAffixIds()->map(fn(Affix $affix) => $affix->affix_id)->toArray());
$result['includeAffixIds'] = implode(',', $this->getIncludeAffixIds()->map(
fn(Affix $affix) => $affix->affix_id
)->toArray());
}

if ($this->getIncludeSpecIds()->isNotEmpty()) {
$result['includeSpecIds'] = implode(',', $this->getIncludeSpecIds()->map(
fn(CharacterClassSpecialization $characterClassSpecialization) => $characterClassSpecialization->specialization_id
)->toArray());
}

if ($this->getMinPeriod() !== null && $this->getMaxPeriod() !== null) {
Expand Down Expand Up @@ -238,6 +275,9 @@ public static function fromArray(array $requestArray): HeatmapDataFilter
$heatmapDataFilter->setIncludeAffixIds(isset($requestArray['includeAffixIds']) ?
Affix::whereIn('affix_id', $requestArray['includeAffixIds'])->get() : collect());

$heatmapDataFilter->setIncludeSpecIds(isset($requestArray['includeSpecIds']) ?
CharacterClassSpecialization::whereIn('specialization_id', $requestArray['includeSpecIds'])->get() : collect());

if (isset($requestArray['minPeriod']) && (int)$requestArray['minPeriod'] > 0) {
$heatmapDataFilter->setMinPeriod($requestArray['minPeriod']);
}
Expand Down
4 changes: 2 additions & 2 deletions app/Service/View/ViewService.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public function getGlobalViewVariables(bool $useCache = true): array
$dungeonsSelectQuery = Dungeon::select('dungeons.*')
->join('expansions', 'dungeons.expansion_id', '=', 'expansions.id')
->orderByRaw('expansions.released_at DESC, dungeons.name');
$raidsSelectQuery = $dungeonsSelectQuery->clone()
$raidsSelectQuery = $dungeonsSelectQuery->clone()
->where('dungeons.raid', true);

$allDungeonsByExpansionId = $dungeonsSelectQuery
Expand Down Expand Up @@ -132,7 +132,7 @@ public function getGlobalViewVariables(bool $useCache = true): array
'releaseChangelogCategories' => ReleaseChangelogCategory::all(),

// Map
'characterClassSpecializations' => CharacterClassSpecialization::all(),
'characterClassSpecializations' => CharacterClassSpecialization::with('class')->get(),
'characterClasses' => CharacterClass::with('specializations')->get(),
// @TODO Classes are loaded fully inside $raceClasses, this shouldn't happen. Find a way to exclude them
'characterRacesClasses' => CharacterRace::with(['classes:character_classes.id'])->orderBy('faction_id')->get(),
Expand Down
31 changes: 31 additions & 0 deletions database/seeders/releases/v11.9.6.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"id": 272,
"release_changelog_id": 279,
"version": "v11.9.6",
"title": "Final heatmap push",
"backup_db": 1,
"silent": 1,
"spotlight": 0,
"released": 0,
"created_at": "2025-01-31T13:23:59+00:00",
"updated_at": "2025-01-31T13:23:59+00:00",
"changelog": {
"id": 279,
"release_id": 272,
"description": null,
"changes": [
{
"release_changelog_id": 279,
"release_changelog_category_id": 13,
"ticket_id": 2682,
"change": "Embedded heatmaps can now be controlled through postMessage."
},
{
"release_changelog_id": 279,
"release_changelog_category_id": 13,
"ticket_id": 2660,
"change": "Added a filter for specializations."
}
]
}
}
2 changes: 1 addition & 1 deletion lang/de_DE/js.php
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@
'filter_enemy_forces_header_complete' => '',
'filter_image_select_affixes_header' => '',
'filter_image_select_dungeons_header' => '',
'filter_image_select_weekly_affix_groups_header' => '',
'filter_input_select_weekly_affix_groups_header' => '',
'filter_input_affix_group_header' => '',
'filter_input_key_level_header' => '',
'filter_input_rating_header' => '',
Expand Down
9 changes: 5 additions & 4 deletions lang/en_US/js.php
Original file line number Diff line number Diff line change
Expand Up @@ -441,11 +441,12 @@
'filter_enemy_forces_header_complete' => 'Enemy forces: complete',
'filter_image_select_affixes_header' => 'Affixes: :number selected',
'filter_image_select_dungeons_header' => 'Dungeons: :number selected',
'filter_image_select_weekly_affix_groups_header' => 'Week: :week',
'filter_input_select_weekly_affix_groups_header' => 'Week: :week',
'filter_input_affix_group_header' => 'Affix groups: :number selected',
'filter_input_key_level_header' => 'Key level: :value',
'filter_input_item_level_header' => 'Item level: :value',
'filter_input_player_deaths_header' => 'Player deaths: :value',
'filter_input_select_specializations_header' => 'Specializations: :specializations',
'filter_input_key_level_header' => 'Key level: :value',
'filter_input_item_level_header' => 'Item level: :value',
'filter_input_player_deaths_header' => 'Player deaths: :value',
'filter_input_rating_header' => 'Rating: :value and higher',
'filter_input_title_header' => 'Title: :value',
'filter_input_expansion_header' => 'Expansion: :value',
Expand Down
2 changes: 1 addition & 1 deletion lang/en_US/specializations.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
],
'hunter' => [
'beast_mastery' => 'Beast Mastery',
'marksman' => 'Marksman',
'marksmanship' => 'Marksmanship',
'survival' => 'Survival',
],
'mage' => [
Expand Down
52 changes: 26 additions & 26 deletions lang/en_US/view_common.php
Original file line number Diff line number Diff line change
Expand Up @@ -315,31 +315,31 @@
'report_an_issue' => 'Report an issue',
],
'heatmapsearch' => [
'settings_title' => 'Map settings',
'enabled' => 'Enabled',
'disabled' => 'Disabled',
'event_type' => 'Event type',
'data_type' => 'Data type',
'npc_death_alt' => 'Enemy death',
'player_death_alt' => 'Player death',
'bloodlust_alt' => 'Bloodlust',
'data_type_title' => 'Enemy position uses the original position of the enemy that was engaged (powered by Auto-Route Creator), player position uses the position of the player when an enemy was engaged (combat log position).',
'filter' => 'Filter',
'loading' => 'Loading',
'key_level' => 'Key level',
'item_level' => 'Item level',
'player_deaths' => 'Player deaths',
'affixes' => 'Affixes',
'affixes_title' => 'Affixes',
'affixes_selected' => '{0} affixes selected',
'weekly_affix_groups' => 'Week',
'weekly_affix_groups_title' => 'Week',
'date_range' => 'Date range',
'date_range_from' => 'From',
'date_range_to' => 'To',
'duration' => 'Duration',
'heat_options' => 'Leaflet.heat Options',
'heat_option' => [
'settings_title' => 'Map settings',
'enabled' => 'Enabled',
'disabled' => 'Disabled',
'event_type' => 'Event type',
'data_type' => 'Data type',
'npc_death_alt' => 'Enemy death',
'player_death_alt' => 'Player death',
'bloodlust_alt' => 'Bloodlust',
'data_type_title' => 'Enemy position uses the original position of the enemy that was engaged (powered by Auto-Route Creator), player position uses the position of the player when an enemy was engaged (combat log position).',
'filter' => 'Filter',
'loading' => 'Loading',
'key_level' => 'Key level',
'item_level' => 'Item level',
'player_deaths' => 'Player deaths',
'affixes' => 'Affixes',
'affixes_title' => 'Affixes',
'affixes_selected' => '{0} affixes selected',
'weekly_affix_groups' => 'Week',
'specializations' => 'Specializations',
'date_range' => 'Date range',
'date_range_from' => 'From',
'date_range_to' => 'To',
'duration' => 'Duration',
'heat_options' => 'Leaflet.heat Options',
'heat_option' => [
'min_opacity' => 'Min opacity',
'max_zoom' => 'Max zoom',
'max' => 'Max',
Expand All @@ -348,7 +348,7 @@
'gradient' => 'Gradient',
'pane' => 'Pane',
],
'data' => [
'data' => [
'dungeon_routes' => 'Showing data from :count runs',
],
],
Expand Down
Loading

0 comments on commit 8994a86

Please sign in to comment.