Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fursuit api #41

Merged
merged 20 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
5fbe2ed
Fursuit API implementation
Aug 11, 2024
ca1f2c6
Fursuit API implementation
Aug 11, 2024
30465fe
Merge remote-tracking branch 'origin/main' into fursuit-api
Balenty Aug 25, 2024
fcb3a7f
Fursuit Catch Code generating + seeder
Balenty Aug 26, 2024
0bf5a05
Fursuit Catch Code database migration
Balenty Aug 26, 2024
c7c1981
FCEA - Logging and User Ranking - Database Part
Balenty Aug 28, 2024
9a135f3
Update Limiter, Based on ID and not IP
Balenty Aug 28, 2024
de62ebd
Adding command fursuit:create-catch-code, Adding Event_Id, newest_cat…
Balenty Aug 30, 2024
8279c37
Adding Fursuit Ranking
Balenty Aug 31, 2024
7c1bdfb
Merging Fursuit and User Ranking Model. DB Transactions for Ranking r…
Balenty Sep 1, 2024
9b31fd5
Providing UserInfo and UserRanking to Frontend
Balenty Sep 5, 2024
62be4a1
Merge remote-tracking branch 'origin/main' into fursuit-api
Balenty Sep 5, 2024
a15fa11
Merge remote-tracking branch 'origin/main' into fursuit-api
Balenty Sep 5, 2024
1767270
Finish Backend Build of User Ranking. myFursuits List build. Further …
Balenty Sep 8, 2024
9906653
restructure FCEA Ranking load. Finished Fursuit Ranking Load
Balenty Sep 9, 2024
4b822f2
Merge remote-tracking branch 'origin/main' into fursuit-api
Balenty Sep 10, 2024
0f8348d
Merge remote-tracking branch 'origin/main' into fursuit-api
Balenty Sep 11, 2024
58c7b13
Merge Issue Fixed
Balenty Sep 11, 2024
dd4cad0
FCEA - Adding Fursuit Catched Total, Prevent user from catching his o…
Balenty Sep 12, 2024
71a598e
Merge branch 'main' into fursuit-api
Thiritin Sep 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 118 additions & 6 deletions app/Http/Controllers/FCEA/DashboardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,38 @@
use App\Models\FCEA\UserCatchRanking;
use App\Models\Fursuit\Fursuit;
use App\Models\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\RateLimiter;
use Inertia\Inertia;
use function Sodium\add;

class DashboardController extends Controller
{
public function index()
{
$myUserInfo = UserCatchRanking::getInfoOfUser(Auth::id());
$userRanking = UserCatchRanking::queryUserRanking()->get();
$rankingSize = 10;

// --------------------------------- Getting User Ranking Data ---------------------------------
$myUserInfo = $this->getMyUserInfo();
$userRanking = $this->getUserRanking($myUserInfo, $rankingSize);
// --------------------------------- Getting Fursuit Ranking Data ---------------------------------
$myFursuitInfos = $this->getMyFursuitInfos($myUserInfo);
$fursuitRanking = $this->getFursuitRanking($myFursuitInfos, $rankingSize);

$myFursuitInfoCatchedTotal = $myFursuitInfos->sum(function ($entry) { return $entry->score; });

return Inertia::render('FCEA/Dashboard', [
'myUserInfo' => $myUserInfo,
'userRanking' => $userRanking,
'myFursuitInfos' => $myFursuitInfos,
'fursuitRanking' => $fursuitRanking,
'myFursuitInfoCatchedTotal' => $myFursuitInfoCatchedTotal, // How many times the user got catched on all fursuits summed up
]);
}
public function catch(UserCatchRequest $request)
{
$this->refreshUserRanking();
$this->refreshFursuitRanking();
$event = \App\Models\Event::getActiveEvent();
if (!$event)
return "No Active Event"; // TODO
Expand All @@ -48,7 +60,13 @@ public function catch(UserCatchRequest $request)
if (!$logEntry->fursuitExist())
{
$logEntry->save();
return Inertia::render('FCEA/Dashboard');
return "Invalid Code";
}

if (Auth::id() == $logEntry->tryGetFursuit()->user_id)
{
$logEntry->save();
return "You can't catch yourself";
}

$logEntry->already_caught =
Expand All @@ -59,7 +77,7 @@ public function catch(UserCatchRequest $request)
if ($logEntry->already_caught)
{
$logEntry->save();
return Inertia::render('FCEA/Dashboard');
return "Fursuit already caught";
}

$logEntry->is_successful = true;
Expand All @@ -70,9 +88,15 @@ public function catch(UserCatchRequest $request)
$userCatch->user_id = Auth::id();
$userCatch->fursuit_id = $logEntry->tryGetFursuit()->id;
$userCatch->save();
$this->refreshRanking();
return Inertia::render('FCEA/Dashboard');
}

public function refreshRanking() {
$this->refreshUserRanking();
$this->refreshFursuitRanking();
}

// Function to build User Ranking. Truncated Table and iterates all users. Similar to the Fursuit Ranking
public function refreshUserRanking() {
$usersOrdered = User::query()
Expand Down Expand Up @@ -187,4 +211,92 @@ protected function IsLimited(int $identifier, string $action = 'fursuit_catch')
RateLimiter::increment($rateLimiterKey);
return 0;
}

private function getMyUserInfo() : UserCatchRanking
{
$myUserInfo = UserCatchRanking::getInfoOfUser(Auth::id()); // Getting own Rank, may be null if user is new

if (!$myUserInfo) { // User not in ranking
$this->refreshRanking(); // refresh it.
$myUserInfo = UserCatchRanking::getInfoOfUser(Auth::id()); // should not be new anymore
}

return $myUserInfo;
}

private function getUserRanking(UserCatchRanking $myUserInfo, int $rankingSize)
{
$topRanking = UserCatchRanking::queryUserRanking()
->whereBetween('id', [1, $rankingSize]) // Top X Ranking
->orderBy('id') // already ordered by rank/score_reached_at
->limit($rankingSize);

$ownIdRange = [$myUserInfo->id - ($rankingSize / 2), $myUserInfo->id + ($rankingSize / 2)];

$ranking = UserCatchRanking::queryUserRanking()
->whereBetween('id', $ownIdRange) // Ranking around own position - Be aware that you need to add separator to the ranking frontend if there is a jump in the ranking
->orderBy('id') // already ordered by rank/score_reached_at
->limit($rankingSize)
->union($topRanking)
->distinct() // remove duplicates
->orderBy('id'); // Last time order to merge union select

// Add Separators when its jumping
return $this->AddPlaceholderOnJump($ranking->get());
}

private function getMyFursuitInfos(UserCatchRanking $myUserInfo) : Collection
{
$myFursuitIDs = $myUserInfo->user->fursuits->pluck('id')->toArray(); // Get all own Fursuit IDs
return UserCatchRanking::getInfoOfFursuits($myFursuitIDs); // Get Ranking info of my fursuits
}

private function getFursuitRanking(Collection $myFursuitInfos, int $rankingSize) : Collection
{
$topRanking = UserCatchRanking::queryFursuitRanking()
->whereBetween('id', [1, $rankingSize]) // Top X Ranking
->orderBy('id') // already ordered by rank/score_reached_at
->limit($rankingSize);

$ranking = $topRanking;

foreach ($myFursuitInfos as $myFursuitInfo) {
$ownIdRange = [$myFursuitInfo->id - ($rankingSize / 2), $myFursuitInfo->id + ($rankingSize / 2)];

$ranking = UserCatchRanking::queryFursuitRanking()
->whereBetween('id', $ownIdRange) // Ranking around own position - Be aware that you need to add separator to the ranking frontend if there is a jump in the ranking
->orderBy('id') // already ordered by rank/score_reached_at
->limit($rankingSize)
->union($ranking)
->distinct() // remove duplicates
->orderBy('id'); // Last time order to merge union select
}

// Add Separators when its jumping
return $this->AddPlaceholderOnJump($ranking->get());
}

private function AddPlaceholderOnJump(Collection $userRanking) : Collection
{
$lastID = $userRanking->first()->id;
// Iterate manually to find jumps in id (every id is used at least once) always starting with 1
foreach ($userRanking as $ranking) {
// Check if we incremented by more than one (jump)
if ($lastID + 1 < $ranking->id) {
$newItem = new UserCatchRanking();
$newItem->id = $lastID + 1; // Use this rank for correct sorting
$newItem->user = new User(); // Consider keeping user/fursuit null for performance
$newItem->user->name = "...";
$newItem->fursuit = new Fursuit();
$newItem->fursuit->name = "...";
$newItem->fursuit->image="filler"; // Crashes if this is null
$userRanking->add($newItem); // Adding a fake item to indicate separators
}

$lastID = $ranking->id;
}

// Should not change the order as it was ordered by id to begin with
return $userRanking->sortBy('id')->values();
}
}
17 changes: 11 additions & 6 deletions app/Models/FCEA/UserCatchRanking.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use App\Models\Fursuit\Fursuit;
use App\Models\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Builder;
Expand Down Expand Up @@ -34,13 +35,17 @@ public function hasFursuit(): bool
return $this->fursuit_id <> null;
}

static public function getInfoOfUser(int $userId): UserCatchRanking
static public function getInfoOfUser(int $userId): UserCatchRanking|null
{
return UserCatchRanking::where('user_id', '=', $userId)->with("user")->first();
return UserCatchRanking::where('user_id', '=', $userId)->with("user")->with("fursuit")->first();
}
static public function getInfoOfFursuit(int $fursuitId): UserCatchRanking
static public function getInfoOfFursuit(int $fursuitID): UserCatchRanking|null
{
return UserCatchRanking::where('fursuit_id', '=', $fursuitId)->with("fursuit")->first();
return UserCatchRanking::where('fursuit_id', '=', $fursuitID)->with("fursuit")->first();
}
static public function getInfoOfFursuits(array $fursuitIDs): Collection
{
return UserCatchRanking::whereBetween('fursuit_id', $fursuitIDs)->with("fursuit")->get();
}

static public function deleteUserRanking(): void
Expand All @@ -52,11 +57,11 @@ static public function deleteFursuitRanking(): void
UserCatchRanking::where('fursuit_id', '<>', null)->delete();
}

static public function queryUserRanking(): \LaravelIdea\Helper\App\Models\FCEA\_IH_UserCatchRanking_QB|Builder
static public function queryUserRanking(): Builder
{
return UserCatchRanking::where('user_id', '<>', null)->with("user");
}
static public function queryFursuitRanking(): \LaravelIdea\Helper\App\Models\FCEA\_IH_UserCatchRanking_QB|Builder
static public function queryFursuitRanking(): Builder
{
return UserCatchRanking::where('fursuit_id', '<>', null)->with("fursuit");
}
Expand Down
2 changes: 1 addition & 1 deletion app/Models/Fursuit/Fursuit.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public function isClaimed()

public function isClaimedBySelf(User $user)
{
return (int) cache()->get($this->getClaimCacheKey()) == $user->id;
return (int)cache()->get($this->getClaimCacheKey()) == $user->id;
}

public function catchedByUsers()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Carbon;

class UserFursuitCatchFactory extends Factory
class UserCatchFactory extends Factory
{
protected $model = UserCatch::class;

Expand Down
17 changes: 11 additions & 6 deletions resources/js/Pages/FCEA/Dashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import {Link, Head, usePage} from '@inertiajs/vue3'
import {useForm} from 'laravel-precognition-vue-inertia'
import Button from 'primevue/button';
import DashboardButton from "@/Components/POS/DashboardButton.vue";


const form = useForm('post', route('fcea.dashboard.catch'), {
Expand All @@ -11,6 +12,9 @@ const props = defineProps(
{
myUserInfo: Object,
userRanking: Object,
myFursuitInfos: Object,
fursuitRanking: Object,
myFursuitInfoCatchedTotal: Number,
}
)

Expand Down Expand Up @@ -39,18 +43,19 @@ function submit() {
<div class="mt-4">
<h5>Top Catchers</h5>
<ul class="list-group">
<li class="list-group-item">Top 1: {{ topCatchers[0] }}</li>
<li class="list-group-item">Top 2...10: {{ topCatchers[1] }}</li>
<li class="list-group-item">...</li>
<li class="list-group-item">Top 704: {{ topCatchers[2] }}</li>
<li class="list-group-item" v-for="i in userRanking"><p v-if="i.user_id == myUserInfo.user_id">[YOU]</p> Top {{i.id}} - {{i.rank}}: {{i.user.name}} [{{i.score}}]</li>
</ul>
</div>

<h4 class="text-center">Place #{{ myFursuitInfos[0].rank }} with {{ myFursuitInfos[0].score }} times being catched</h4>
<p class="text-center" v-if="myFursuitInfos[0].score_till_next ==! 0"><small>{{ myFursuitInfos[0].score_till_next }} more to advance to the next place</small></p>
<p class="text-center"><small>{{ myFursuitInfos[0].others_behind }} behind you</small></p>
<p class="text-center"><small>You were been {{ myFursuitInfoCatchedTotal }} catched between all fursuits</small></p>

<div class="mt-4">
<h5>Top Fursuiters</h5>
<ul class="list-group">
<li class="list-group-item">Top 1: {{ topFursuiters[0] }}</li>
<li class="list-group-item">Top 2...10: {{ topFursuiters[1] }}</li>
<li class="list-group-item" v-for="i in fursuitRanking">Top {{i.id}} - {{i.rank}}: {{i.fursuit.name??'error'}} [{{i.score}}]</li>
</ul>
</div>
</div>
Expand Down
Loading
Loading