User Rank System
User ranking and badge system providing gamification elements, reputation tracking, and user engagement metrics across the Extra Chill Platform.
Rank Tiers Structure
Rank Configuration
// Rank tier definitions
function ec_get_rank_tiers() {
return [
'newcomer' => [
'name' => 'Newcomer',
'description' => 'Just getting started',
'min_points' => 0,
'badge_icon' => 'seedling',
'color' => '#22c55e',
'privileges' => ['basic_posting', 'profile_edit']
],
'contributor' => [
'name' => 'Contributor',
'description' => 'Active community member',
'min_points' => 100,
'badge_icon' => 'star',
'color' => '#3b82f6',
'privileges' => ['enhanced_posting', 'comment_moderation']
],
'expert' => [
'name' => 'Expert',
'description' => 'Respected community voice',
'min_points' => 500,
'badge_icon' => 'award',
'color' => '#8b5cf6',
'privileges' => ['content_moderation', 'user_mention']
],
'veteran' => [
'name' => 'Veteran',
'description' => 'Long-time pillar of the community',
'min_points' => 1000,
'badge_icon' => 'crown',
'color' => '#f59e0b',
'privileges' => ['advanced_moderation', 'exclusive_content']
],
'legend' => [
'name' => 'Legend',
'description' => 'Community icon and inspiration',
'min_points' => 2500,
'badge_icon' => 'gem',
'color' => '#ef4444',
'privileges' => ['full_moderation', 'community_leadership']
]
];
}
Rank Calculation
// Calculate user's current rank
function ec_calculate_user_rank($user_id) {
$user_points = ec_get_user_points($user_id);
$rank_tiers = ec_get_rank_tiers();
$current_rank = 'newcomer';
foreach ($rank_tiers as $tier_key => $tier_data) {
if ($user_points >= $tier_data['min_points']) {
$current_rank = $tier_key;
}
}
return $current_rank;
}
Points System
Point Actions
// Point awarding actions
function ec_get_point_actions() {
return [
'post_created' => 10,
'comment_posted' => 5,
'comment_received' => 2,
'topic_created' => 15,
'reply_posted' => 3,
'helpful_vote_received' => 5,
'daily_login' => 2,
'profile_completed' => 20,
'avatar_uploaded' => 10,
'first_post' => 25,
'welcome_message' => 5,
'referral_joined' => 50,
'content_shared' => 3,
'badge_earned' => 15
];
}
Points Awarding
// Award points to user
function ec_award_points($user_id, $action, $context = []) {
$point_actions = ec_get_point_actions();
$points = $point_actions[$action] ?? 0;
if ($points > 0) {
$current_points = ec_get_user_points($user_id);
$new_points = $current_points + $points;
// Update user points
update_user_meta($user_id, 'rank_points', $new_points);
// Log point award
ec_log_point_award($user_id, $action, $points, $context);
// Check for rank progression
ec_check_rank_progression($user_id, $new_points);
// Trigger action for other integrations
do_action('ec_points_awarded', $user_id, $action, $points, $context);
}
return $points;
}
Points Tracking
// Get user's total points
function ec_get_user_points($user_id) {
return (int) get_user_meta($user_id, 'rank_points', true) ?: 0;
}
// Get points breakdown by action
function ec_get_points_breakdown($user_id, $days = 30) {
global $wpdb;
$table_name = $wpdb->prefix . 'ec_points_log';
$date_limit = date('Y-m-d H:i:s', strtotime("-{$days} days"));
return $wpdb->get_results($wpdb->prepare(
"SELECT action, COUNT(*) as count, SUM(points) as total_points
FROM {$table_name}
WHERE user_id = %d AND created_at > %s
GROUP BY action
ORDER BY total_points DESC",
$user_id, $date_limit
));
}
Badge System
Badge Definitions
// Available badges
function ec_get_badges() {
return [
'pioneer' => [
'name' => 'Pioneer',
'description' => 'One of the first 100 members',
'icon' => 'compass',
'color' => '#f59e0b',
'award_type' => 'automatic',
'condition' => 'early_adopter'
],
'helpful' => [
'name' => 'Helpful',
'description' => 'Received 50 helpful votes',
'icon' => 'hand-heart',
'color' => '#10b981',
'award_type' => 'automatic',
'condition' => 'helpful_votes_50'
],
'veteran' => [
'name' => 'Veteran',
'description' => 'Member for over a year',
'icon' => 'calendar-check',
'color' => '#6366f1',
'award_type' => 'automatic',
'condition' => 'member_one_year'
],
'creator' => [
'name' => 'Creator',
'description' => 'Created 100+ posts',
'icon' => 'pen-tool',
'color' => '#8b5cf6',
'award_type' => 'automatic',
'condition' => 'posts_100'
],
'moderator' => [
'name' => 'Moderator',
'description' => 'Community moderator',
'icon' => 'shield',
'color' => '#ef4444',
'award_type' => 'manual'
]
];
}
Badge Awarding
// Award badge to user
function ec_award_badge($user_id, $badge_key) {
$badges = ec_get_user_badges($user_id);
if (!in_array($badge_key, $badges)) {
$badges[] = $badge_key;
update_user_meta($user_id, 'rank_badges', $badges);
// Award bonus points for badge
ec_award_points($user_id, 'badge_earned');
// Log badge award
ec_log_badge_award($user_id, $badge_key);
// Trigger action
do_action('ec_badge_awarded', $user_id, $badge_key);
return true;
}
return false;
}
Badge Display
// Get user's badges
function ec_get_user_badges($user_id) {
return get_user_meta($user_id, 'rank_badges', true) ?: [];
}
// Render user badges
function ec_render_user_badges($user_id, $size = 'small') {
$badges = ec_get_user_badges($user_id);
$all_badges = ec_get_badges();
if (empty($badges)) {
return '';
}
$output = '<div class="user-badges ' . esc_attr($size) . '">';
foreach ($badges as $badge_key) {
if (isset($all_badges[$badge_key])) {
$badge = $all_badges[$badge_key];
$output .= '<span class="badge" title="' . esc_attr($badge['description']) . '">';
$output .= '<span class="badge-icon" style="color: ' . esc_attr($badge['color']) . '">' . ec_get_icon($badge['icon']) . '</span>';
$output .= '</span>';
}
}
$output .= '</div>';
return $output;
}
Rank Progression
Progress Tracking
// Calculate rank progress
function ec_get_rank_progress($user_id) {
$user_points = ec_get_user_points($user_id);
$current_rank = ec_calculate_user_rank($user_id);
$rank_tiers = ec_get_rank_tiers();
$current_rank_data = $rank_tiers[$current_rank];
$next_rank_key = ec_get_next_rank_key($current_rank);
if (!$next_rank_key) {
// User is at highest rank
return [
'current_rank' => $current_rank,
'current_points' => $user_points,
'rank_name' => $current_rank_data['name'],
'progress_percent' => 100,
'points_to_next' => 0,
'is_max_rank' => true
];
}
$next_rank_data = $rank_tiers[$next_rank_key];
$points_in_current_rank = $user_points - $current_rank_data['min_points'];
$points_needed_for_next = $next_rank_data['min_points'] - $current_rank_data['min_points'];
$progress_percent = min(100, ($points_in_current_rank / $points_needed_for_next) * 100);
return [
'current_rank' => $current_rank,
'next_rank' => $next_rank_key,
'current_points' => $user_points,
'rank_name' => $current_rank_data['name'],
'next_rank_name' => $next_rank_data['name'],
'progress_percent' => round($progress_percent),
'points_to_next' => $next_rank_data['min_points'] - $user_points,
'is_max_rank' => false
];
}
Rank Progression Check
// Check if user has progressed to next rank
function ec_check_rank_progression($user_id, $new_points) {
$old_rank = get_user_meta($user_id, 'current_rank', true) ?: 'newcomer';
$new_rank = ec_calculate_user_rank($user_id);
if ($new_rank !== $old_rank) {
// User ranked up!
ec_handle_rank_promotion($user_id, $old_rank, $new_rank);
}
}
// Handle rank promotion
function ec_handle_rank_promotion($user_id, $old_rank, $new_rank) {
// Update user's current rank
update_user_meta($user_id, 'current_rank', $new_rank);
// Award bonus points for ranking up
$rank_bonus = ec_get_rank_promotion_bonus($new_rank);
if ($rank_bonus > 0) {
ec_award_points($user_id, 'rank_promotion', ['bonus_points' => $rank_bonus]);
}
// Check for rank-specific badges
ec_check_rank_badges($user_id, $new_rank);
// Send notification
ec_send_rank_promotion_notification($user_id, $old_rank, $new_rank);
// Trigger action
do_action('ec_rank_promoted', $user_id, $old_rank, $new_rank);
}
Leaderboard System
Leaderboard Generation
// Get top users by points
function ec_get_leaderboard($limit = 10, $period = 'all_time') {
global $wpdb;
$table_name = $wpdb->prefix . 'usermeta';
$date_condition = '';
if ($period === 'monthly') {
$date_condition = "AND um2.meta_key = 'monthly_points' AND um2.meta_value";
} elseif ($period === 'weekly') {
$date_condition = "AND um2.meta_key = 'weekly_points' AND um2.meta_value";
}
$results = $wpdb->get_results($wpdb->prepare(
"SELECT u.ID, u.display_name, um1.meta_value as points
FROM {$wpdb->users} u
JOIN {$table_name} um1 ON u.ID = um1.user_id
LEFT JOIN {$table_name} um2 ON u.ID = um2.user_id
WHERE um1.meta_key = 'rank_points' {$date_condition}
ORDER BY CAST(um1.meta_value AS UNSIGNED) DESC
LIMIT %d",
$limit
));
return array_map(function($row) {
return [
'user_id' => $row->ID,
'display_name' => $row->display_name,
'points' => (int) $row->points,
'rank' => ec_calculate_user_rank($row->ID),
'badges' => ec_get_user_badges($row->ID)
];
}, $results);
}
Leaderboard Display
// Render leaderboard widget
function ec_render_leaderboard($limit = 10) {
$leaders = ec_get_leaderboard($limit);
$current_user_id = get_current_user_id();
$output = '<div class="leaderboard-widget">';
$output .= '<h3>Top Contributors</h3>';
foreach ($leaders as $index => $leader) {
$position = $index + 1;
$is_current_user = $leader['user_id'] === $current_user_id;
$output .= '<div class="leaderboard-entry ' . ($is_current_user ? 'current-user' : '') . '">';
$output .= '<span class="position">' . $position . '</span>';
$output .= '<span class="user-info">';
$output .= get_avatar($leader['user_id'], 24);
$output .= '<span class="name">' . esc_html($leader['display_name']) . '</span>';
$output .= '</span>';
$output .= '<span class="points">' . number_format($leader['points']) . ' pts</span>';
$output .= '</div>';
}
$output .= '</div>';
return $output;
}
Integration Points
Community Integration
// Award points for community actions
function ec_community_points_integration($action, $user_id, $context) {
$point_actions = ec_get_point_actions();
switch ($action) {
case 'bbp_new_topic':
ec_award_points($user_id, 'topic_created', $context);
break;
case 'bbp_new_reply':
ec_award_points($user_id, 'reply_posted', $context);
break;
case 'helpful_vote':
ec_award_points($context['author_id'], 'helpful_vote_received', $context);
break;
}
}
Artist Platform Integration
// Artist-specific ranks and badges
function ec_artist_rank_integration($artist_id, $action) {
$user_id = get_post_meta($artist_id, 'user_id', true);
if ($user_id) {
switch ($action) {
case 'profile_created':
ec_award_points($user_id, 'artist_profile_created');
ec_award_badge($user_id, 'artist');
break;
case 'show_added':
ec_award_points($user_id, 'show_added');
break;
}
}
}
API Endpoints
Points API
// Register points endpoints
function ec_register_points_api_endpoints() {
register_rest_route('extrachill/v1', '/users/(?P<user_id>d+)/points', [
'methods' => 'GET',
'callback' => 'ec_api_get_user_points',
'permission_callback' => function() {
return is_user_logged_in();
}
]);
register_rest_route('extrachill/v1', '/leaderboard', [
'methods' => 'GET',
'callback' => 'ec_api_get_leaderboard',
'permission_callback' => '__return_true'
]);
}
Performance Optimization
Points Caching
// Cache user points
function ec_cached_get_user_points($user_id) {
$cache_key = "ec_user_points_{$user_id}";
$cached_points = wp_cache_get($cache_key, 'ec_points');
if ($cached_points !== false) {
return $cached_points;
}
$points = ec_get_user_points($user_id);
wp_cache_set($cache_key, $points, 'ec_points', 300); // 5 minutes
return $points;
}
Database Optimization
- Indexed columns for queries
- Optimized leaderboard queries
- Efficient badge lookups
- Scheduled cleanup routines
Security and Validation
Points Security
// Validate point awarding
function ec_validate_point_award($user_id, $action, $points) {
// Check user exists
if (!get_userdata($user_id)) {
return false;
}
// Validate action
$valid_actions = array_keys(ec_get_point_actions());
if (!in_array($action, $valid_actions)) {
return false;
}
// Rate limiting for automated awards
if (ec_should_rate_limit_point_award($user_id, $action)) {
return false;
}
return true;
}
Anti-Exploitation
- Rate limiting for point awards
- Validation of point actions
- Audit logging for all changes
- Duplicate prevention mechanisms
Analytics and Reporting
Points Analytics
// Get points statistics
function ec_get_points_statistics($days = 30) {
global $wpdb;
$table_name = $wpdb->prefix . 'ec_points_log';
$date_limit = date('Y-m-d H:i:s', strtotime("-{$days} days"));
return [
'total_points_awarded' => $wpdb->get_var($wpdb->prepare(
"SELECT SUM(points) FROM {$table_name} WHERE created_at > %s",
$date_limit
)),
'active_users' => $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(DISTINCT user_id) FROM {$table_name} WHERE created_at > %s",
$date_limit
)),
'top_action' => ec_get_top_point_action($date_limit),
'daily_average' => ec_get_daily_points_average($date_limit)
];
}