Submit Leaderboard Score
The submit leaderboard score method allows players to submit their scores to specific leaderboards. This is used for ongoing competitions and ranking systems outside of tournaments.
Overview
The submitScore method:
- Submits player scores to specific leaderboards
- Updates leaderboard rankings in real-time
- Validates player participation and score validity
- Returns status code indicating success or failure
Method Signature
public function submitScore(string $gameID, string $leaderboardID, int $score): int
Parameters
Required Parameters
gameID(String) - The Game ID for the leaderboardleaderboardID(String) - The Leaderboard ID to submit score toscore(int) - The player's score to submit
Return Value
Returns an integer status code:
- Positive value - Score submitted successfully
- Zero or negative - Submission failed
Basic Usage
Simple Score Submission
use Veniso\Moitribe\Sdk\modules\classes\MoitribeApi;
$moitribe = new MoitribeApi([
'gameid' => 'your-game-id',
'channelid' => 'your-channel-id',
'playerid' => 'player-123'
]);
try {
$result = $moitribe->leaderboardRequestsHandler->submitScore(
'your-game-id',
'leaderboard-123',
2500
);
if ($result > 0) {
echo "Score submitted successfully!\n";
echo "Submission ID: " . $result . "\n";
} else {
echo "Failed to submit score\n";
echo "Error code: " . $result . "\n";
}
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
Score Submission with Validation
function submitLeaderboardScore($gameId, $leaderboardId, $score, $gameSessionData) {
global $moitribe;
try {
// Validate score
if ($score < 0) {
return ['success' => false, 'message' => 'Score cannot be negative'];
}
// Check if leaderboard exists and is active
$leaderboards = $moitribe->leaderboardRequestsHandler->getLeaderboards($gameId);
$targetLeaderboard = null;
foreach ($leaderboards as $leaderboard) {
if ($leaderboard->getId() === $leaderboardId) {
$targetLeaderboard = $leaderboard;
break;
}
}
if (!$targetLeaderboard) {
return ['success' => false, 'message' => 'Leaderboard not found'];
}
if ($targetLeaderboard->getStatus() !== 'active') {
return ['success' => false, 'message' => 'Leaderboard is not active'];
}
// Submit score
$result = $moitribe->leaderboardRequestsHandler->submitScore(
$gameId,
$leaderboardId,
$score
);
if ($result > 0) {
// Log submission
$this->logScoreSubmission($leaderboardId, $score, $gameSessionData, $result);
return [
'success' => true,
'message' => 'Score submitted successfully',
'submission_id' => $result,
'leaderboard_name' => $targetLeaderboard->getName()
];
} else {
return [
'success' => false,
'message' => 'Failed to submit score',
'error_code' => $result
];
}
} catch (Exception $e) {
error_log("Leaderboard score submission error: " . $e->getMessage());
return [
'success' => false,
'message' => 'Server error occurred'
];
}
}
// Usage
$gameSession = [
'level' => 12,
'time_played' => 900, // 15 minutes
'difficulty' => 'hard',
'character' => 'warrior'
];
$result = submitLeaderboardScore('your-game-id', 'leaderboard-456', 3200, $gameSession);
if ($result['success']) {
echo "Success: " . $result['message'] . "\n";
echo "Leaderboard: " . $result['leaderboard_name'] . "\n";
echo "Submission ID: " . $result['submission_id'] . "\n";
} else {
echo "Error: " . $result['message'] . "\n";
}
Integration Examples
Real-time Score Submission
class LeaderboardScoreManager {
private $moitribe;
private $gameId;
private $scoreQueue = [];
public function __construct($moitribe, $gameId) {
$this->moitribe = $moitribe;
$this->gameId = $gameId;
}
public function queueScoreSubmission($leaderboardId, $score, $metadata = []) {
$this->scoreQueue[] = [
'leaderboard_id' => $leaderboardId,
'score' => $score,
'timestamp' => time(),
'metadata' => $metadata,
'attempts' => 0
];
return count($this->scoreQueue);
}
public function processScoreQueue() {
$processed = 0;
$failed = 0;
foreach ($this->scoreQueue as $index => &$scoreSubmission) {
try {
$scoreSubmission['attempts']++;
$result = $this->moitribe->leaderboardRequestsHandler->submitScore(
$this->gameId,
$scoreSubmission['leaderboard_id'],
$scoreSubmission['score']
);
if ($result > 0) {
$this->logSuccessfulSubmission($scoreSubmission, $result);
unset($this->scoreQueue[$index]);
$processed++;
} else {
$this->logFailedSubmission($scoreSubmission, $result);
$failed++;
// Remove from queue after 3 attempts
if ($scoreSubmission['attempts'] >= 3) {
unset($this->scoreQueue[$index]);
}
}
} catch (Exception $e) {
error_log("Score processing error: " . $e->getMessage());
$failed++;
if ($scoreSubmission['attempts'] >= 3) {
unset($this->scoreQueue[$index]);
}
}
// Small delay to avoid overwhelming API
usleep(50000); // 0.05 seconds
}
return [
'processed' => $processed,
'failed' => $failed,
'remaining' => count($this->scoreQueue)
];
}
public function getQueueStatus() {
return [
'total_queued' => count($this->scoreQueue),
'queue' => $this->scoreQueue
];
}
private function logSuccessfulSubmission($submission, $submissionId) {
$logData = [
'submission_id' => $submissionId,
'leaderboard_id' => $submission['leaderboard_id'],
'score' => $submission['score'],
'timestamp' => $submission['timestamp'],
'metadata' => $submission['metadata'],
'status' => 'success',
'processed_at' => date('Y-m-d H:i:s')
];
error_log("Score submitted successfully: " . json_encode($logData));
}
private function logFailedSubmission($submission, $errorCode) {
$logData = [
'leaderboard_id' => $submission['leaderboard_id'],
'score' => $submission['score'],
'timestamp' => $submission['timestamp'],
'attempts' => $submission['attempts'],
'error_code' => $errorCode,
'status' => 'failed'
];
error_log("Score submission failed: " . json_encode($logData));
}
}
// Usage
$scoreManager = new LeaderboardScoreManager($moitribe, 'your-game-id');
// Queue multiple scores during gameplay
$scoreManager->queueScoreSubmission('daily-leaderboard', 1500, [
'level' => 10,
'character' => 'mage'
]);
$scoreManager->queueScoreSubmission('weekly-leaderboard', 2800, [
'level' => 10,
'character' => 'mage'
]);
// Process queue (could be called periodically)
$result = $scoreManager->processScoreQueue();
echo "Processed: {$result['processed']}, Failed: {$result['failed']}, Remaining: {$result['remaining']}\n";
Web Score Submission Handler
function handleLeaderboardScoreSubmission() {
global $moitribe;
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
return;
}
$input = json_decode(file_get_contents('php://input'), true);
$requiredFields = ['game_id', 'leaderboard_id', 'player_id', 'score'];
foreach ($requiredFields as $field) {
if (!isset($input[$field])) {
http_response_code(400);
echo json_encode(['error' => "Missing required field: $field"]);
return;
}
}
$gameId = $input['game_id'];
$leaderboardId = $input['leaderboard_id'];
$playerId = $input['player_id'];
$score = (int)$input['score'];
$metadata = $input['metadata'] ?? [];
try {
// Validate inputs
if (empty($gameId) || empty($leaderboardId) || empty($playerId)) {
throw new InvalidArgumentException('Game ID, Leaderboard ID, and Player ID are required');
}
if (!is_int($score) || $score < 0) {
throw new InvalidArgumentException('Score must be a non-negative integer');
}
// Submit score
$result = $moitribe->leaderboardRequestsHandler->submitScore(
$gameId,
$leaderboardId,
$score
);
if ($result > 0) {
// Log submission
$this->logWebScoreSubmission($gameId, $leaderboardId, $playerId, $score, $metadata, $result);
http_response_code(200);
echo json_encode([
'success' => true,
'message' => 'Score submitted successfully',
'submission_id' => $result
]);
} else {
http_response_code(400);
echo json_encode([
'success' => false,
'message' => 'Failed to submit score',
'error_code' => $result
]);
}
} catch (InvalidArgumentException $e) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
} catch (Exception $e) {
http_response_code(500);
echo json_encode(['success' => false, 'message' => 'Server error occurred']);
error_log("Leaderboard score API error: " . $e->getMessage());
}
}
function logWebScoreSubmission($gameId, $leaderboardId, $playerId, $score, $metadata, $submissionId) {
$logData = [
'submission_id' => $submissionId,
'game_id' => $gameId,
'leaderboard_id' => $leaderboardId,
'player_id' => $playerId,
'score' => $score,
'metadata' => $metadata,
'ip_address' => $_SERVER['REMOTE_ADDR'] ?? 'unknown',
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
'timestamp' => date('Y-m-d H:i:s')
];
error_log("Web score submission: " . json_encode($logData));
}
// Route handler
if (strpos($_SERVER['REQUEST_URI'], '/api/leaderboard/submit-score') !== false) {
handleLeaderboardScoreSubmission();
}
Error Handling
Common Error Scenarios
- Invalid leaderboard ID - Leaderboard doesn't exist
- Leaderboard not active - Leaderboard is disabled or archived
- Invalid score - Negative or unrealistic score values
- Player not eligible - Player doesn't meet requirements
- Duplicate submission - Same score submitted multiple times
- Network issues - API communication problems
Error Handling Example
function safeSubmitLeaderboardScore($gameId, $leaderboardId, $score) {
global $moitribe;
try {
// Validate inputs
if (empty($gameId) || empty($leaderboardId)) {
throw new InvalidArgumentException("Game ID and Leaderboard ID are required");
}
if (!is_int($score) || $score < 0) {
throw new InvalidArgumentException("Score must be a non-negative integer");
}
$result = $moitribe->leaderboardRequestsHandler->submitScore(
$gameId,
$leaderboardId,
$score
);
if ($result > 0) {
return [
'success' => true,
'submission_id' => $result,
'message' => 'Score submitted successfully'
];
} else {
$errorMessage = $this->getScoreSubmissionErrorMessage($result);
return [
'success' => false,
'message' => $errorMessage,
'error_code' => $result
];
}
} catch (InvalidArgumentException $e) {
return [
'success' => false,
'message' => 'Invalid input: ' . $e->getMessage()
];
} catch (Exception $e) {
error_log("Leaderboard score submission error: " . $e->getMessage());
return [
'success' => false,
'message' => 'Failed to submit score'
];
}
}
function getScoreSubmissionErrorMessage($errorCode) {
switch ($errorCode) {
case 0:
return 'Score submission failed';
case -1:
return 'Leaderboard not found';
case -2:
return 'Leaderboard is not active';
case -3:
return 'Invalid score value';
case -4:
return 'Player not eligible for this leaderboard';
case -5:
return 'Duplicate score submission';
default:
return 'Unknown error occurred';
}
}
Best Practices
-
Validate Score Values
- Ensure scores are non-negative integers
- Check for realistic score ranges
- Validate against game rules
-
Implement Rate Limiting
- Avoid spamming score submissions
- Implement cooldown periods between submissions
- Queue submissions for batch processing
-
Handle Network Issues
- Implement retry mechanisms for failed submissions
- Store failed submissions for later retry
- Provide offline submission capabilities
-
Log Submission Events
- Track all score submissions for analytics
- Monitor for unusual patterns or cheating
- Maintain audit trails
Related Methods
- List Leaderboards - Find available leaderboards
- Get Leaderboard Data - Check rankings after submission
- Submit Tournament Score - Submit tournament-specific scores