Skip to content

Commit c445c18

Browse files
committed
refactor(awards): centralize award logic in AutomaticPrizeAwarder
1 parent 4140eef commit c445c18

File tree

4 files changed

+78
-52
lines changed

4 files changed

+78
-52
lines changed

website/app/GeoKrety/Service/Award/AutomaticPrizeAwarder.php

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace GeoKrety\Service\Award;
44

5+
use GeoKrety\Model\Awards;
6+
use GeoKrety\Model\AwardsWon;
57
use GeoKrety\Model\Move;
68

79
class AutomaticPrizeAwarder {
@@ -36,7 +38,7 @@ private function handleMove(Move $move): void {
3638

3739
if ($service instanceof AwardServiceInterface) {
3840
if ($service->shouldAward($move)) {
39-
$service->awardUser($move);
41+
$this->awardUser($move, $service);
4042
}
4143
}
4244
} catch (\Exception $e) {
@@ -46,4 +48,50 @@ private function handleMove(Move $move): void {
4648
}
4749
}
4850
}
51+
52+
/**
53+
* Award the user using the provided service.
54+
*/
55+
private function awardUser(Move $move, AwardServiceInterface $service): void {
56+
// Load award with cache (1 hour TTL)
57+
$award = new Awards();
58+
$award->load(['name = ?', $service->getAwardName()], ttl: 3600);
59+
60+
if ($award->dry()) {
61+
// Award doesn't exist - log and return
62+
error_log(sprintf("Award '%s' not found in database", $service->getAwardName()));
63+
64+
return;
65+
}
66+
67+
// Check if already awarded (with cache)
68+
$awardWon = new AwardsWon();
69+
$awardWon->load(['holder = ? and award = ?', $move->author->id, $award->id], ttl: 3600);
70+
71+
if (!$awardWon->dry()) {
72+
return; // Already awarded
73+
}
74+
75+
// Create and save award
76+
$awardWon = new AwardsWon();
77+
$awardWon->holder = $move->author->id;
78+
$awardWon->award = $award->id;
79+
$awardWon->description = $service->getAwardDescription($move);
80+
$awardWon->save();
81+
82+
// Invalidate cache immediately
83+
$invalidateCheck = new AwardsWon();
84+
$invalidateCheck->load(['holder = ? and award = ?', $move->author->id, $award->id], ttl: -1);
85+
86+
// Fire event for audit trail
87+
$events = \Sugar\Event::instance();
88+
$events->emit('award.given', [
89+
'award_id' => $award->id,
90+
'award_name' => $service->getAwardName(),
91+
'user_id' => $move->author->id,
92+
'move_id' => $move->id,
93+
'geokret_id' => $move->geokret->id,
94+
'automatic' => true,
95+
]);
96+
}
4997
}

website/app/GeoKrety/Service/Award/AwardServiceInterface.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ interface AwardServiceInterface {
1111
public function shouldAward(Move $move): bool;
1212

1313
/**
14-
* Award the user for this move.
14+
* Get the award name for this service.
1515
*/
16-
public function awardUser(Move $move): void;
16+
public function getAwardName(): string;
17+
18+
/**
19+
* Get the award description for this move.
20+
*/
21+
public function getAwardDescription(Move $move): string;
1722
}

website/app/GeoKrety/Service/Award/EasterEggAwardService.php

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
use GeoKrety\GeokretyType;
66
use GeoKrety\LogType;
7-
use GeoKrety\Model\Awards;
8-
use GeoKrety\Model\AwardsWon;
97
use GeoKrety\Model\Move;
108

119
class EasterEggAwardService implements AwardServiceInterface {
@@ -22,43 +20,16 @@ public function shouldAward(Move $move): bool {
2220
}
2321

2422
/**
25-
* Award the Hidden GeoKrety Finder award to the user.
23+
* Get the award name for this service.
2624
*/
27-
public function awardUser(Move $move): void {
28-
// Load award with cache (1 hour TTL)
29-
$award = new Awards();
30-
$award->load(['name = ?', self::AWARD_NAME], ttl: 3600);
31-
32-
if ($award->dry()) {
33-
// Award doesn't exist - log and return
34-
error_log("Award '{self::AWARD_NAME}' not found in database");
35-
36-
return;
37-
}
38-
39-
// Create award assignment
40-
$awardWon = new AwardsWon();
41-
$awardWon->holder = $move->author->id;
42-
$awardWon->award = $award->id;
43-
$awardWon->description = 'Automatically awarded for discovering a Hidden GeoKrety';
44-
45-
try {
46-
$awardWon->save();
25+
public function getAwardName(): string {
26+
return self::AWARD_NAME;
27+
}
4728

48-
// Fire event for audit trail
49-
$events = \Sugar\Event::instance();
50-
$events->emit('award.given', [
51-
'award_id' => $award->id,
52-
'award_name' => self::AWARD_NAME,
53-
'user_id' => $move->author->id,
54-
'move_id' => $move->id,
55-
'geokret_id' => $move->geokret->id,
56-
'automatic' => true,
57-
]);
58-
} catch (\Exception $e) {
59-
// Database constraint violation (duplicate award) - silently ignore
60-
// Other errors are also ignored to not break move processing
61-
// This is logged in AutomaticPrizeAwarder
62-
}
29+
/**
30+
* Get the award description for this move.
31+
*/
32+
public function getAwardDescription(Move $move): string {
33+
return 'Automatically awarded for discovering a Hidden GeoKrety';
6334
}
6435
}

website/db/tests/test-300-awards.sql

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,28 @@ INSERT INTO "gk_users" ("id", "username", "registration_ip") VALUES (2, 'test 2'
99
INSERT INTO "gk_users" ("id", "username", "registration_ip") VALUES (3, 'test 3', '127.0.0.1');
1010

1111
-- Test awards
12-
INSERT INTO "gk_awards" ("id", "name", "description", "filename", "type") VALUES (1, 'Test Award', 'Test award description', 'test.svg', 'manual');
13-
INSERT INTO "gk_awards" ("id", "name", "description", "filename", "type") VALUES (2, 'Hidden GeoKrety Finder', 'Has discovered one Hidden GeoKrety', 'hidden-finder.svg', 'manual');
14-
INSERT INTO "gk_awards" ("id", "name", "description", "filename", "type") VALUES (3, 'Another Award', 'Another test award', 'another.svg', 'manual');
12+
-- Starting high as the db dumps already contains awards;
13+
INSERT INTO "gk_awards" ("id", "name", "description", "filename", "type") VALUES (1000001, 'Test Award', 'Test award description', 'test.svg', 'manual');
14+
INSERT INTO "gk_awards" ("id", "name", "description", "filename", "type") VALUES (1000002, 'Hidden GeoKrety Finder', 'Has discovered one Hidden GeoKrety', 'hidden-finder.svg', 'manual');
15+
INSERT INTO "gk_awards" ("id", "name", "description", "filename", "type") VALUES (1000003, 'Another Award', 'Another test award', 'another.svg', 'manual');
1516

1617
-- Test basic award assignment works
17-
SELECT lives_ok($$INSERT INTO "gk_awards_won" ("holder", "award", "description") VALUES (1, 1, 'Test award assignment')$$, 'Basic award assignment should work');
1818

1919
-- Test unique constraint (holder, award) - user cannot get same award twice
20+
SELECT lives_ok($$INSERT INTO "gk_awards_won" ("holder", "award", "description") VALUES (1, 1000001, 'Test award assignment')$$, 'Basic award assignment should work');
21+
2022
SELECT throws_ok(
21-
$$INSERT INTO "gk_awards_won" ("holder", "award", "description") VALUES (1, 1, 'Duplicate award')$$,
23+
$$INSERT INTO "gk_awards_won" ("holder", "award", "description") VALUES (1, 1000001, 'Duplicate award')$$,
2224
23505,
2325
'duplicate key value violates unique constraint "gk_awards_won_holder_award"',
2426
'Should prevent duplicate awards to same user'
2527
);
2628

2729
-- Test same award can be given to different users
28-
SELECT lives_ok($$INSERT INTO "gk_awards_won" ("holder", "award", "description") VALUES (2, 1, 'Same award to different user')$$, 'Same award can be given to different users');
30+
SELECT lives_ok($$INSERT INTO "gk_awards_won" ("holder", "award", "description") VALUES (2, 1000001, 'Same award to different user')$$, 'Same award can be given to different users');
2931

3032
-- Test different awards can be given to same user
31-
SELECT lives_ok($$INSERT INTO "gk_awards_won" ("holder", "award", "description") VALUES (1, 3, 'Different award to same user')$$, 'Different awards can be given to same user');
33+
SELECT lives_ok($$INSERT INTO "gk_awards_won" ("holder", "award", "description") VALUES (1, 1000003, 'Different award to same user')$$, 'Different awards can be given to same user');
3234

3335
-- Test Easter Egg GeoKrety setup (type 10)
3436
INSERT INTO "gk_geokrety" ("id", "name", "type", "owner", "holder", "created_on_datetime") VALUES (1, 'Easter Egg Test', 10, 1, 1, '2024-07-21 12:15:00+00');
@@ -37,13 +39,13 @@ INSERT INTO "gk_geokrety" ("id", "name", "type", "owner", "holder", "created_on_
3739
INSERT INTO "gk_geokrety" ("id", "name", "type", "owner", "holder", "created_on_datetime") VALUES (4, 'Another Easter Egg', 10, 2, 2, '2024-07-21 12:15:00+00');
3840

3941
-- Test award assignment can happen to different users for Hidden GeoKrety Finder
40-
SELECT lives_ok($$INSERT INTO "gk_awards_won" ("holder", "award", "description") VALUES (1, 2, 'Found Easter Egg')$$, 'User 1 can get Hidden GeoKrety Finder award');
41-
SELECT lives_ok($$INSERT INTO "gk_awards_won" ("holder", "award", "description") VALUES (2, 2, 'Found Easter Egg')$$, 'User 2 can get Hidden GeoKrety Finder award');
42-
SELECT lives_ok($$INSERT INTO "gk_awards_won" ("holder", "award", "description") VALUES (3, 2, 'Found Easter Egg')$$, 'User 3 can get Hidden GeoKrety Finder award');
42+
SELECT lives_ok($$INSERT INTO "gk_awards_won" ("holder", "award", "description") VALUES (1, 1000002, 'Found Easter Egg')$$, 'User 1 can get Hidden GeoKrety Finder award');
43+
SELECT lives_ok($$INSERT INTO "gk_awards_won" ("holder", "award", "description") VALUES (2, 1000002, 'Found Easter Egg')$$, 'User 2 can get Hidden GeoKrety Finder award');
44+
SELECT lives_ok($$INSERT INTO "gk_awards_won" ("holder", "award", "description") VALUES (3, 1000002, 'Found Easter Egg')$$, 'User 3 can get Hidden GeoKrety Finder award');
4345

4446
-- Test same user cannot get Hidden GeoKrety Finder award twice
4547
SELECT throws_ok(
46-
$$INSERT INTO "gk_awards_won" ("holder", "award", "description") VALUES (1, 2, 'Duplicate Easter Egg award')$$,
48+
$$INSERT INTO "gk_awards_won" ("holder", "award", "description") VALUES (1, 1000002, 'Duplicate Easter Egg award')$$,
4749
23505,
4850
'duplicate key value violates unique constraint "gk_awards_won_holder_award"',
4951
'Should prevent duplicate Hidden GeoKrety Finder awards to same user'

0 commit comments

Comments
 (0)