232 lines
5.9 KiB
PHP
232 lines
5.9 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use Illuminate\Support\Collection;
|
|
use Kreait\Firebase\Factory;
|
|
use Kreait\Firebase\Database;
|
|
|
|
class FirebaseQuestionService
|
|
{
|
|
protected Database $database;
|
|
|
|
public function __construct()
|
|
{
|
|
$credentialsPath = (string) config('services.firebase.credentials');
|
|
$databaseUrl = config('services.firebase.database_url');
|
|
|
|
if (!$credentialsPath || !file_exists($credentialsPath)) {
|
|
throw new \RuntimeException('Firebase credentials file not found.');
|
|
}
|
|
|
|
$factory = (new Factory())->withServiceAccount($credentialsPath);
|
|
|
|
if (!empty($databaseUrl)) {
|
|
$factory = $factory->withDatabaseUri($databaseUrl);
|
|
}
|
|
|
|
$this->database = $factory->createDatabase();
|
|
}
|
|
|
|
public function getQuestions(string $eventId, string $sessionId): Collection
|
|
{
|
|
$path = sprintf('events/%s/sessions/%s/questions', $eventId, $sessionId);
|
|
|
|
$value = $this->database->getReference($path)->getValue();
|
|
|
|
if (!is_array($value)) {
|
|
return collect();
|
|
}
|
|
|
|
return collect($value)
|
|
->map(function ($item, $key) {
|
|
if (is_array($item)) {
|
|
$item['firebase_key'] = $item['firebase_key'] ?? $key;
|
|
return $item;
|
|
}
|
|
|
|
return [
|
|
'firebase_key' => $key,
|
|
'question' => $item,
|
|
];
|
|
})
|
|
->values();
|
|
}
|
|
|
|
public function getTopQuestions(string $eventId, string $sessionId, int $limit = 5): Collection
|
|
{
|
|
return $this->sortQuestions($this->getQuestions($eventId, $sessionId))
|
|
->take($limit)
|
|
->values();
|
|
}
|
|
|
|
public function sortQuestions(Collection $questions): Collection
|
|
{
|
|
return $questions
|
|
->sort(function ($a, $b) {
|
|
$aScore = $this->score($a);
|
|
$bScore = $this->score($b);
|
|
|
|
if ($aScore === $bScore) {
|
|
return $this->timestamp($b) <=> $this->timestamp($a);
|
|
}
|
|
|
|
return $bScore <=> $aScore;
|
|
})
|
|
->values();
|
|
}
|
|
|
|
protected function score(array $item): int
|
|
{
|
|
$candidates = [
|
|
$item['likes'] ?? null,
|
|
$item['upvotes'] ?? null,
|
|
$item['votes'] ?? null,
|
|
$item['score'] ?? null,
|
|
];
|
|
|
|
foreach ($candidates as $candidate) {
|
|
if (is_numeric($candidate)) {
|
|
return (int) $candidate;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
protected function timestamp(array $item): int
|
|
{
|
|
$raw = $item['created_at'] ?? $item['createdAt'] ?? null;
|
|
|
|
if (is_numeric($raw)) {
|
|
return (int) $raw;
|
|
}
|
|
|
|
if (is_string($raw)) {
|
|
$parsed = strtotime($raw);
|
|
if ($parsed !== false) {
|
|
return $parsed;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use Illuminate\Support\Collection;
|
|
use Kreait\Firebase\Factory;
|
|
use Kreait\Firebase\Database;
|
|
|
|
class FirebaseQuestionService
|
|
{
|
|
protected Database $database;
|
|
|
|
public function __construct()
|
|
{
|
|
$credentialsPath = (string) config('services.firebase.credentials');
|
|
$databaseUrl = config('services.firebase.database_url');
|
|
|
|
if (!$credentialsPath || !file_exists($credentialsPath)) {
|
|
throw new \RuntimeException('Firebase credentials file not found.');
|
|
}
|
|
|
|
$factory = (new Factory())->withServiceAccount($credentialsPath);
|
|
|
|
if (!empty($databaseUrl)) {
|
|
$factory = $factory->withDatabaseUri($databaseUrl);
|
|
}
|
|
|
|
$this->database = $factory->createDatabase();
|
|
}
|
|
|
|
public function getQuestions(string $eventId, string $sessionId): Collection
|
|
{
|
|
$path = sprintf('events/%s/sessions/%s/questions', $eventId, $sessionId);
|
|
|
|
$value = $this->database->getReference($path)->getValue();
|
|
|
|
if (!is_array($value)) {
|
|
return collect();
|
|
}
|
|
|
|
return collect($value)
|
|
->map(function ($item, $key) {
|
|
if (is_array($item)) {
|
|
$item['firebase_key'] = $item['firebase_key'] ?? $key;
|
|
return $item;
|
|
}
|
|
|
|
return [
|
|
'firebase_key' => $key,
|
|
'question' => $item,
|
|
];
|
|
})
|
|
->values();
|
|
}
|
|
|
|
public function getTopQuestions(string $eventId, string $sessionId, int $limit = 5): Collection
|
|
{
|
|
return $this->sortQuestions($this->getQuestions($eventId, $sessionId))
|
|
->take($limit)
|
|
->values();
|
|
}
|
|
|
|
public function sortQuestions(Collection $questions): Collection
|
|
{
|
|
return $questions
|
|
->sort(function ($a, $b) {
|
|
$aScore = $this->score($a);
|
|
$bScore = $this->score($b);
|
|
|
|
if ($aScore === $bScore) {
|
|
return $this->timestamp($b) <=> $this->timestamp($a);
|
|
}
|
|
|
|
return $bScore <=> $aScore;
|
|
})
|
|
->values();
|
|
}
|
|
|
|
protected function score(array $item): int
|
|
{
|
|
$candidates = [
|
|
$item['likes'] ?? null,
|
|
$item['upvotes'] ?? null,
|
|
$item['votes'] ?? null,
|
|
$item['score'] ?? null,
|
|
];
|
|
|
|
foreach ($candidates as $candidate) {
|
|
if (is_numeric($candidate)) {
|
|
return (int) $candidate;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
protected function timestamp(array $item): int
|
|
{
|
|
$raw = $item['created_at'] ?? $item['createdAt'] ?? null;
|
|
|
|
if (is_numeric($raw)) {
|
|
return (int) $raw;
|
|
}
|
|
|
|
if (is_string($raw)) {
|
|
$parsed = strtotime($raw);
|
|
if ($parsed !== false) {
|
|
return $parsed;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|