Get Tournament Data
The groupTournamentData method retrieves detailed information about a specific tournament, including rules, scoring, prizes, and sub-tournaments. Use this after getting the tournament list from groupTournamentMeta to show players comprehensive tournament details.
Overview
Use this method to:
- Display complete tournament information to players
- Show tournament rules and scoring criteria
- Get prize information and reward details
- Access sub-tournament data for complex events
- Check detailed tournament timing and status
Method Signature
MoitribeSDK(gameId, 'groupTournamentData', {
tournamentid: string,
callback: (result) => {
// Handle response
}
});
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tournamentid | string | Yes | Unique identifier of the tournament |
callback | function | Yes | Function to handle the response |
Response Format
{
success: boolean;
tournament: TournamentData;
msg?: string; // Error message if success is false
}
interface TournamentData {
id: string; // Tournament unique identifier
name: string; // Tournament display name
description: string; // Full tournament description
rules: string; // Tournament rules and scoring details
startTime: number; // Tournament start timestamp (Unix)
endTime: number; // Tournament end timestamp (Unix)
status: string; // 'upcoming', 'active', 'ended', 'results'
type: string; // 'weekly', 'daily', 'special', 'seasonal'
scoreType: string; // 'high' (higher is better), 'low' (lower is better), 'time'
maxParticipants?: number; // Maximum participants (if limited)
currentParticipants: number; // Current number of participants
prizes?: Prize[]; // Prize information
subTournaments?: SubTournament[]; // Nested tournaments
requirements?: Requirement[]; // Participation requirements
leaderboard?: LeaderboardInfo; // Associated leaderboard info
}
interface Prize {
rank: number; // Rank position (1, 2, 3...)
description: string; // Prize description
value?: string; // Prize value or type
icon?: string; // Prize icon URL
}
interface SubTournament {
id: string; // Sub-tournament ID
name: string; // Sub-tournament name
description: string; // Sub-tournament description
rules: string; // Specific rules for this sub-tournament
scoreType: string; // Scoring type for this sub-tournament
startTime: number; // Sub-tournament start time
endTime: number; // Sub-tournament end time
maxParticipants?: number; // Max participants for this sub-tournament
currentParticipants: number; // Current participants
}
interface Requirement {
type: string; // 'level', 'achievement', 'item'
value: string | number; // Required value
description: string; // Human-readable requirement
}
JavaScript Example
// Get detailed tournament information
MoitribeSDK('my-game-id', 'groupTournamentData', {
tournamentid: 'weekly-challenge-001',
callback: (result) => {
if (result.success) {
const tournament = result.tournament;
console.log('Tournament Details:', tournament);
// Display tournament information
console.log(`Name: ${tournament.name}`);
console.log(`Description: ${tournament.description}`);
console.log(`Status: ${tournament.status}`);
console.log(`Start: ${new Date(tournament.startTime)}`);
console.log(`End: ${new Date(tournament.endTime)}`);
console.log(`Participants: ${tournament.currentParticipants}/${tournament.maxParticipants || '∞'}`);
// Display rules
console.log('Rules:', tournament.rules);
// Display prizes if available
if (tournament.prizes && tournament.prizes.length > 0) {
console.log('Prizes:');
tournament.prizes.forEach(prize => {
console.log(` Rank ${prize.rank}: ${prize.description}`);
});
}
// Display sub-tournaments if available
if (tournament.subTournaments && tournament.subTournaments.length > 0) {
console.log('Sub-tournaments:');
tournament.subTournaments.forEach(sub => {
console.log(` ${sub.name}: ${sub.description}`);
});
}
} else {
console.error('Failed to get tournament data:', result.msg);
}
}
});
TypeScript Example
import MoitribeSDK from '@veniso/moitribe-js';
interface TournamentData {
id: string;
name: string;
description: string;
rules: string;
startTime: number;
endTime: number;
status: string;
type: string;
scoreType: string;
maxParticipants?: number;
currentParticipants: number;
prizes?: Prize[];
subTournaments?: SubTournament[];
requirements?: Requirement[];
leaderboard?: LeaderboardInfo;
}
interface Prize {
rank: number;
description: string;
value?: string;
icon?: string;
}
interface SubTournament {
id: string;
name: string;
description: string;
rules: string;
scoreType: string;
startTime: number;
endTime: number;
maxParticipants?: number;
currentParticipants: number;
}
interface TournamentDataResponse {
success: boolean;
tournament: TournamentData;
msg?: string;
}
// Get tournament data with proper typing
MoitribeSDK('my-game-id', 'groupTournamentData', {
tournamentid: 'weekly-challenge-001',
callback: (result: TournamentDataResponse) => {
if (result.success) {
displayTournamentDetails(result.tournament);
} else {
handleTournamentError(result.msg);
}
}
});
function displayTournamentDetails(tournament: TournamentData) {
const container = document.getElementById('tournament-details');
// Tournament header
const header = document.createElement('div');
header.className = 'tournament-header';
header.innerHTML = `
<h1>${tournament.name}</h1>
<p class="tournament-description">${tournament.description}</p>
<div class="tournament-meta">
<span class="status ${tournament.status}">${tournament.status.toUpperCase()}</span>
<span class="type">${tournament.type}</span>
<span class="participants">${tournament.currentParticipants} participants</span>
</div>
`;
// Tournament timing
const timing = document.createElement('div');
timing.className = 'tournament-timing';
timing.innerHTML = `
<h3>Tournament Schedule</h3>
<p><strong>Start:</strong> ${new Date(tournament.startTime).toLocaleString()}</p>
<p><strong>End:</strong> ${new Date(tournament.endTime).toLocaleString()}</p>
<p><strong>Duration:</strong> ${calculateDuration(tournament.startTime, tournament.endTime)}</p>
`;
container.appendChild(header);
container.appendChild(timing);
// Rules section
if (tournament.rules) {
const rules = document.createElement('div');
rules.className = 'tournament-rules';
rules.innerHTML = `
<h3>Rules & Scoring</h3>
<div class="rules-content">${formatRules(tournament.rules)}</div>
<p><strong>Score Type:</strong> ${formatScoreType(tournament.scoreType)}</p>
`;
container.appendChild(rules);
}
// Prizes section
if (tournament.prizes && tournament.prizes.length > 0) {
const prizes = document.createElement('div');
prizes.className = 'tournament-prizes';
prizes.innerHTML = `
<h3>Prizes</h3>
${tournament.prizes.map(prize => `
<div class="prize-item">
<span class="rank">Rank ${prize.rank}</span>
<span class="description">${prize.description}</span>
</div>
`).join('')}
`;
container.appendChild(prizes);
}
// Sub-tournaments section
if (tournament.subTournaments && tournament.subTournaments.length > 0) {
const subTournaments = document.createElement('div');
subTournaments.className = 'sub-tournaments';
subTournaments.innerHTML = `
<h3>Sub-Tournaments</h3>
${tournament.subTournaments.map(sub => `
<div class="sub-tournament-item">
<h4>${sub.name}</h4>
<p>${sub.description}</p>
<p><strong>Scoring:</strong> ${formatScoreType(sub.scoreType)}</p>
<p><strong>Participants:</strong> ${sub.currentParticipants}/${sub.maxParticipants || '∞'}</p>
</div>
`).join('')}
`;
container.appendChild(subTournaments);
}
// Action buttons
const actions = document.createElement('div');
actions.className = 'tournament-actions';
if (tournament.status === 'active') {
actions.innerHTML = `
<button onclick="joinTournament('${tournament.id}')" class="btn-primary">
Join Tournament
</button>
`;
} else if (tournament.status === 'upcoming') {
actions.innerHTML = `
<button disabled class="btn-disabled">
Starts ${new Date(tournament.startTime).toLocaleString()}
</button>
`;
} else if (tournament.status === 'results') {
actions.innerHTML = `
<button onclick="viewResults('${tournament.id}')" class="btn-secondary">
View Results
</button>
`;
}
container.appendChild(actions);
}
function formatScoreType(scoreType: string): string {
const types = {
'high': 'Higher scores are better',
'low': 'Lower scores are better',
'time': 'Faster times are better'
};
return types[scoreType] || scoreType;
}
function formatRules(rules: string): string {
// Convert plain text rules to formatted HTML
return rules.split('\n').map(line => {
if (line.trim().startsWith('-')) {
return `<li>${line.trim().substring(1).trim()}</li>`;
} else if (line.trim()) {
return `<p>${line}</p>`;
}
return '';
}).join('');
}
function calculateDuration(startTime: number, endTime: number): string {
const duration = endTime - startTime;
const days = Math.floor(duration / (1000 * 60 * 60 * 24));
const hours = Math.floor((duration % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
if (days > 0) {
return `${days} day${days > 1 ? 's' : ''} ${hours} hour${hours > 1 ? 's' : ''}`;
} else {
return `${hours} hour${hours > 1 ? 's' : ''}`;
}
}
Common Use Cases
Tournament Details Page
Create a comprehensive tournament details view:
function loadTournamentDetails(tournamentId) {
MoitribeSDK('my-game-id', 'groupTournamentData', {
tournamentid: tournamentId,
callback: (result) => {
if (result.success) {
renderTournamentPage(result.tournament);
} else {
showError('Failed to load tournament details');
}
}
});
}
function renderTournamentPage(tournament) {
// Update page title
document.title = `${tournament.name} - Tournament Details`;
// Render tournament header with status
renderTournamentHeader(tournament);
// Render tournament schedule
renderSchedule(tournament);
// Render rules and scoring
renderRules(tournament);
// Render prizes
renderPrizes(tournament);
// Render sub-tournaments
renderSubTournaments(tournament);
// Render appropriate action buttons
renderActionButtons(tournament);
}
function renderTournamentHeader(tournament) {
const header = document.getElementById('tournament-header');
const statusClass = `status-${tournament.status}`;
header.innerHTML = `
<div class="tournament-banner">
<h1>${tournament.name}</h1>
<p class="tournament-description">${tournament.description}</p>
<div class="tournament-badges">
<span class="badge ${statusClass}">${tournament.status.toUpperCase()}</span>
<span class="badge badge-type">${tournament.type}</span>
<span class="badge badge-score">${tournament.scoreType.toUpperCase()} SCORE</span>
</div>
</div>
<div class="tournament-stats">
<div class="stat-item">
<span class="stat-value">${tournament.currentParticipants}</span>
<span class="stat-label">Participants</span>
</div>
${tournament.maxParticipants ? `
<div class="stat-item">
<span class="stat-value">${tournament.maxParticipants}</span>
<span class="stat-label">Max Players</span>
</div>
` : ''}
<div class="stat-item">
<span class="stat-value">${calculateTimeLeft(tournament.endTime)}</span>
<span class="stat-label">Time Left</span>
</div>
</div>
`;
}
Tournament Requirements Check
Check if player meets tournament requirements:
function checkTournamentRequirements(tournamentId) {
MoitribeSDK('my-game-id', 'groupTournamentData', {
tournamentid: tournamentId,
callback: (result) => {
if (result.success) {
const tournament = result.tournament;
if (tournament.requirements && tournament.requirements.length > 0) {
checkPlayerRequirements(tournament.requirements, tournament);
} else {
// No requirements, can join directly
enableJoinButton(tournament.id);
}
}
}
});
}
function checkPlayerRequirements(requirements, tournament) {
// Check each requirement
Promise.all(
requirements.map(req => checkRequirement(req))
).then(results => {
const allMet = results.every(result => result);
if (allMet) {
enableJoinButton(tournament.id);
} else {
showRequirementsMessage(requirements);
}
});
}
function checkRequirement(requirement) {
return new Promise((resolve) => {
switch (requirement.type) {
case 'level':
// Check player level
getPlayerLevel().then(level => {
resolve(level >= requirement.value);
});
break;
case 'achievement':
// Check if player has achievement
hasAchievement(requirement.value).then(has => {
resolve(has);
});
break;
default:
resolve(true); // Unknown requirement, assume met
}
});
}
function showRequirementsMessage(requirements) {
const requirementsList = requirements
.map(req => `• ${req.description}`)
.join('\n');
showMessage(`You need to meet these requirements to join:\n\n${requirementsList}`);
}
Sub-Tournament Navigation
Handle navigation between sub-tournaments:
function renderSubTournaments(tournament) {
const container = document.getElementById('sub-tournaments');
if (!tournament.subTournaments || tournament.subTournaments.length === 0) {
container.style.display = 'none';
return;
}
container.innerHTML = `
<h2>Sub-Tournaments</h2>
<div class="sub-tournament-tabs">
${tournament.subTournaments.map((sub, index) => `
<button
class="tab-btn ${index === 0 ? 'active' : ''}"
onclick="showSubTournament('${sub.id}', this)"
>
${sub.name}
</button>
`).join('')}
</div>
<div class="sub-tournament-content">
${tournament.subTournaments.map((sub, index) => `
<div
id="sub-${sub.id}"
class="sub-tournament-panel ${index === 0 ? 'active' : ''}"
>
<h3>${sub.name}</h3>
<p>${sub.description}</p>
<div class="sub-rules">
<h4>Rules</h4>
<p>${sub.rules}</p>
</div>
<div class="sub-stats">
<span>Scoring: ${formatScoreType(sub.scoreType)}</span>
<span>Participants: ${sub.currentParticipants}/${sub.maxParticipants || '∞'}</span>
</div>
</div>
`).join('')}
</div>
`;
}
function showSubTournament(subId, button) {
// Hide all panels
document.querySelectorAll('.sub-tournament-panel').forEach(panel => {
panel.classList.remove('active');
});
// Remove active class from all buttons
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.classList.remove('active');
});
// Show selected panel
document.getElementById(`sub-${subId}`).classList.add('active');
button.classList.add('active');
}
Tournament Countdown Timer
Show dynamic countdown for tournament timing:
function startTournamentCountdown(tournament) {
const countdownElement = document.getElementById('tournament-countdown');
function updateCountdown() {
const now = Date.now();
let targetTime, message;
if (tournament.status === 'upcoming') {
targetTime = tournament.startTime;
message = 'Tournament starts in:';
} else if (tournament.status === 'active') {
targetTime = tournament.endTime;
message = 'Tournament ends in:';
} else {
countdownElement.style.display = 'none';
return;
}
const timeLeft = targetTime - now;
if (timeLeft <= 0) {
countdownElement.innerHTML = '<span class="countdown-ended">Tournament ended</span>';
// Refresh tournament data
setTimeout(() => {
loadTournamentDetails(tournament.id);
}, 1000);
return;
}
const days = Math.floor(timeLeft / (1000 * 60 * 60 * 24));
const hours = Math.floor((timeLeft % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((timeLeft % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((timeLeft % (1000 * 60)) / 1000);
countdownElement.innerHTML = `
<div class="countdown-label">${message}</div>
<div class="countdown-timer">
${days > 0 ? `<span class="countdown-unit">${days}d</span>` : ''}
<span class="countdown-unit">${hours}h</span>
<span class="countdown-unit">${minutes}m</span>
<span class="countdown-unit">${seconds}s</span>
</div>
`;
requestAnimationFrame(updateCountdown);
}
updateCountdown();
}
Error Handling
Handle common errors when retrieving tournament data:
MoitribeSDK('my-game-id', 'groupTournamentData', {
tournamentid: tournamentId,
callback: (result) => {
if (result.success) {
displayTournamentDetails(result.tournament);
} else {
// Handle specific error cases
if (result.msg.includes('not found')) {
showTournamentNotFound();
} else if (result.msg.includes('access')) {
showAccessDenied();
} else if (result.msg.includes('maintenance')) {
showMaintenanceMessage();
} else {
showGenericError(result.msg);
}
}
}
});
function showTournamentNotFound() {
document.getElementById('tournament-details').innerHTML = `
<div class="error-message">
<h2>Tournament Not Found</h2>
<p>This tournament doesn't exist or has been removed.</p>
<button onclick="loadTournamentList()">View All Tournaments</button>
</div>
`;
}
function showAccessDenied() {
document.getElementById('tournament-details').innerHTML = `
<div class="error-message">
<h2>Access Denied</h2>
<p>You don't have permission to view this tournament.</p>
<p>Please check your account status or contact support.</p>
</div>
`;
}
Best Practices
Data Validation
Validate tournament data before displaying:
function validateTournamentData(tournament) {
const required = ['id', 'name', 'description', 'status', 'startTime', 'endTime'];
const missing = required.filter(field => !tournament[field]);
if (missing.length > 0) {
console.error('Missing tournament fields:', missing);
return false;
}
// Validate timestamps
if (tournament.startTime >= tournament.endTime) {
console.error('Invalid tournament timing');
return false;
}
// Validate status
const validStatuses = ['upcoming', 'active', 'ended', 'results'];
if (!validStatuses.includes(tournament.status)) {
console.error('Invalid tournament status:', tournament.status);
return false;
}
return true;
}
Progressive Loading
Load tournament data progressively for better UX:
function loadTournamentProgressively(tournamentId) {
// Show loading state
showLoadingState();
// Load basic tournament data first
MoitribeSDK('my-game-id', 'groupTournamentData', {
tournamentid: tournamentId,
callback: (result) => {
if (result.success && validateTournamentData(result.tournament)) {
const tournament = result.tournament;
// Show basic info immediately
showBasicTournamentInfo(tournament);
// Load additional data asynchronously
loadAdditionalTournamentData(tournament);
} else {
showError('Failed to load tournament');
}
}
});
}
function showBasicTournamentInfo(tournament) {
// Show header, description, basic timing
renderTournamentHeader(tournament);
renderBasicInfo(tournament);
}
function loadAdditionalTournamentData(tournament) {
// Load prizes, sub-tournaments, etc.
if (tournament.prizes) {
renderPrizes(tournament.prizes);
}
if (tournament.subTournaments) {
renderSubTournaments(tournament);
}
// Hide loading state
hideLoadingState();
}
Next Steps
After getting tournament data:
- Join Tournament - Register players for participation
- Submit Score - Submit scores during active tournaments
- Get Results - View tournament results when finished
Related topics:
- Get Metadata - List available tournaments first
- Tournament Lifecycle - Understand tournament states
- Authentication - Required for tournament participation