Skip to content

Commit 738dd98

Browse files
committed
fix: ambiguous item blueprint labels
1 parent 68a1fd5 commit 738dd98

3 files changed

Lines changed: 115 additions & 11 deletions

File tree

app/Models/Game/ItemData.php

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,28 @@ public function getDescriptionManufacturerAttribute()
9494
*/
9595
public function getBlueprintAttribute(): array
9696
{
97-
return $this->craftingBlueprints()
97+
$craftingBlueprints = $this->craftingBlueprints()
9898
->filter(fn (BlueprintData $blueprintData): bool => $blueprintData->blueprint !== null)
99-
->map(fn (BlueprintData $blueprintData): array => $this->craftingBlueprintSummary($blueprintData))
100-
->values()
99+
->values();
100+
101+
/** @var array<string, bool> $ambiguousOutputNames */
102+
$ambiguousOutputNames = array_fill_keys(
103+
$craftingBlueprints
104+
->map(
105+
fn (BlueprintData $blueprintData): ?string => $this->normalizeCraftingBlueprintLabel($blueprintData->output_name)
106+
)
107+
->filter(fn (?string $outputName): bool => $outputName !== null)
108+
->countBy()
109+
->filter(fn (int $count): bool => $count > 1)
110+
->keys()
111+
->all(),
112+
true
113+
);
114+
115+
return $craftingBlueprints
116+
->map(
117+
fn (BlueprintData $blueprintData): array => $this->craftingBlueprintSummary($blueprintData, $ambiguousOutputNames)
118+
)
101119
->all();
102120
}
103121

@@ -452,24 +470,47 @@ private function craftingBlueprints(): Collection
452470
}
453471

454472
/**
473+
* @param array<string, bool> $ambiguousOutputNames
455474
* @return array{uuid: string, name: string}
456475
*/
457-
private function craftingBlueprintSummary(BlueprintData $blueprintData): array
476+
private function craftingBlueprintSummary(BlueprintData $blueprintData, array $ambiguousOutputNames): array
458477
{
459478
return [
460479
'uuid' => $blueprintData->blueprint->uuid,
461-
'name' => $this->resolveCraftingBlueprintName($blueprintData),
480+
'name' => $this->resolveCraftingBlueprintName($blueprintData, $ambiguousOutputNames),
462481
];
463482
}
464483

465-
private function resolveCraftingBlueprintName(BlueprintData $blueprintData): string
484+
/**
485+
* @param array<string, bool> $ambiguousOutputNames
486+
*/
487+
private function resolveCraftingBlueprintName(BlueprintData $blueprintData, array $ambiguousOutputNames): string
466488
{
467-
foreach ([$blueprintData->output_name, $blueprintData->key, $blueprintData->blueprint->uuid] as $candidate) {
468-
if (is_string($candidate) && trim($candidate) !== '') {
469-
return trim($candidate);
489+
$outputName = $this->normalizeCraftingBlueprintLabel($blueprintData->output_name);
490+
491+
if ($outputName !== null && ! isset($ambiguousOutputNames[$outputName])) {
492+
return $outputName;
493+
}
494+
495+
foreach ([$blueprintData->key, $blueprintData->blueprint->uuid, $outputName] as $candidate) {
496+
$normalizedCandidate = $this->normalizeCraftingBlueprintLabel($candidate);
497+
498+
if ($normalizedCandidate !== null) {
499+
return $normalizedCandidate;
470500
}
471501
}
472502

473503
return $blueprintData->blueprint->uuid;
474504
}
505+
506+
private function normalizeCraftingBlueprintLabel(mixed $candidate): ?string
507+
{
508+
if (! is_string($candidate)) {
509+
return null;
510+
}
511+
512+
$candidate = trim($candidate);
513+
514+
return $candidate !== '' ? $candidate : null;
515+
}
475516
}

tests/Feature/Api/Game/ItemControllerTest.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,71 @@
134134
->and($craftingLookupQuery)->toContain('"key"');
135135
});
136136

137+
it('uses recipe keys when multiple crafting blueprints share the same output name', function (): void {
138+
$item = Item::factory()->create();
139+
140+
ItemData::factory()
141+
->for($item)
142+
->for($this->gameVersion, 'gameVersion')
143+
->for($this->manufacturer)
144+
->create([
145+
'name' => 'Karna Rifle',
146+
'type' => 'Weapon',
147+
'class_name' => 'karna_rifle',
148+
'classification' => 'FPS.Weapon.Rifle',
149+
'data' => ['stdItem' => []],
150+
]);
151+
152+
$alphaBlueprint = Blueprint::factory()->create();
153+
$betaBlueprint = Blueprint::factory()->create();
154+
155+
BlueprintData::factory()
156+
->for($alphaBlueprint, 'blueprint')
157+
->for($this->gameVersion, 'gameVersion')
158+
->create([
159+
'key' => 'BP_KARNA_RIFLE_DEFAULT',
160+
'output_item_uuid' => $item->uuid,
161+
'output_name' => 'Karna Rifle',
162+
'is_available_by_default' => false,
163+
'data' => [
164+
'output' => [
165+
'uuid' => $item->uuid,
166+
'name' => 'Karna Rifle',
167+
'class' => 'bp_karna_rifle_default',
168+
],
169+
'tiers' => [],
170+
],
171+
]);
172+
173+
BlueprintData::factory()
174+
->for($betaBlueprint, 'blueprint')
175+
->for($this->gameVersion, 'gameVersion')
176+
->create([
177+
'key' => 'BP_KARNA_RIFLE_EVENT',
178+
'output_item_uuid' => $item->uuid,
179+
'output_name' => 'Karna Rifle',
180+
'is_available_by_default' => false,
181+
'data' => [
182+
'output' => [
183+
'uuid' => $item->uuid,
184+
'name' => 'Karna Rifle',
185+
'class' => 'bp_karna_rifle_event',
186+
],
187+
'tiers' => [],
188+
],
189+
]);
190+
191+
$response = $this->getJson("/api/items/{$item->uuid}");
192+
193+
$response->assertSuccessful()
194+
->assertJsonPath('data.is_craftable', true)
195+
->assertJsonCount(2, 'data.blueprint')
196+
->assertJsonPath('data.blueprint.0.uuid', $alphaBlueprint->uuid)
197+
->assertJsonPath('data.blueprint.0.name', 'BP_KARNA_RIFLE_DEFAULT')
198+
->assertJsonPath('data.blueprint.1.uuid', $betaBlueprint->uuid)
199+
->assertJsonPath('data.blueprint.1.name', 'BP_KARNA_RIFLE_EVENT');
200+
});
201+
137202
it('uses uuid-specific lookup before name or class_name fallbacks', function (): void {
138203
$item = Item::factory()->create();
139204
$decoyItem = Item::factory()->create();

tests/Feature/WelcomePageTest.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
'Comm-Links',
2626
'Vehicles',
2727
'All Items',
28-
'Blueprints',
2928
'Stats',
3029
'Systems',
3130
'Celestial Objects',
@@ -34,7 +33,6 @@
3433
]);
3534

3635
$response->assertSee('name="filter[name]"', false);
37-
$response->assertSee(route('web.blueprints.index'));
3836

3937
$response->assertDontSee('Admin');
4038
});

0 commit comments

Comments
 (0)