AI-based personalization system for iGaming experiences
iGaming personalization isn't just about game recommendations. It's about tailoring the lobby, bonus offers, responsible gaming thresholds, and interface to each player's individual profile. Responsible Gambling (RG) tools aren't an optional feature, but a regulatory standard.
Game lobby customization
import numpy as np
import pandas as pd
from sklearn.ensemble import GradientBoostingClassifier
from anthropic import Anthropic
import json
class iGamingPersonalizationEngine:
"""Персонализация для онлайн-казино и ставок"""
GAME_CATEGORIES = ['slots', 'live_casino', 'table_games', 'poker', 'sports_betting', 'virtual_sports']
def build_player_preferences(self, session_history: pd.DataFrame,
player_id: str) -> dict:
"""Профиль предпочтений игрока"""
player_sessions = session_history[session_history['player_id'] == player_id]
if player_sessions.empty:
return {'player_id': player_id, 'is_new': True}
# Предпочтения по категориям (взвешенные по времени игры)
category_time = player_sessions.groupby('game_category')['session_duration_min'].sum()
total_time = category_time.sum()
category_preferences = (category_time / max(total_time, 1)).to_dict()
# Предпочтения по ставкам
bet_sizes = player_sessions['avg_bet_size'].dropna()
# Сессионные паттерны
return {
'player_id': player_id,
'category_preferences': category_preferences,
'top_game_category': category_time.idxmax() if len(category_time) > 0 else 'slots',
'avg_bet_size': bet_sizes.mean() if len(bet_sizes) > 0 else 0,
'avg_session_duration_min': player_sessions['session_duration_min'].mean(),
'preferred_session_time': int(player_sessions['session_start_hour'].mode().iloc[0]) if len(player_sessions) > 0 else 19,
'device_preference': player_sessions['device'].mode().iloc[0] if 'device' in player_sessions.columns else 'mobile',
'total_sessions': len(player_sessions),
'volatility_preference': self._infer_volatility_preference(player_sessions),
}
def _infer_volatility_preference(self, sessions: pd.DataFrame) -> str:
"""Предпочтение волатильности из паттернов игры"""
if 'game_volatility' not in sessions.columns:
return 'medium'
preferred_vol = sessions.groupby('game_volatility')['session_duration_min'].sum().idxmax()
return preferred_vol if preferred_vol else 'medium'
def personalize_lobby(self, player_profile: dict,
available_games: pd.DataFrame,
n_featured: int = 6) -> dict:
"""Персонализация лобби казино"""
if player_profile.get('is_new'):
return self._default_lobby(available_games, n_featured)
top_category = player_profile.get('top_game_category', 'slots')
vol_pref = player_profile.get('volatility_preference', 'medium')
games = available_games.copy()
# Скоринг игр
games['score'] = 0.0
# Категорийный матч
cat_prefs = player_profile.get('category_preferences', {})
games['score'] += games['category'].map(cat_prefs).fillna(0.05) * 0.40
# Волатильность
games['score'] += (games.get('volatility', 'medium') == vol_pref).astype(float) * 0.20
# Новинки и популярные
games['score'] += games.get('is_new', False).astype(float) * 0.10
games['score'] += (games.get('popularity_rank', 100) < 20).astype(float) * 0.15
# Джекпоты для высокорисковых игроков
if vol_pref == 'high':
games['score'] += games.get('has_jackpot', False).astype(float) * 0.15
else:
games['score'] += 0.15 # Равномерный бонус для обычных игр
featured = games.nlargest(n_featured, 'score').to_dict('records')
return {
'featured_games': featured,
'recommended_category': top_category,
'personalized_banner': self._get_personalized_banner(player_profile),
'bonus_offer': self._select_bonus(player_profile)
}
def _default_lobby(self, games: pd.DataFrame, n: int) -> dict:
return {
'featured_games': games.nlargest(n, 'popularity_rank').to_dict('records'),
'recommended_category': 'slots',
'personalized_banner': None,
'bonus_offer': {'type': 'welcome_bonus'}
}
def _get_personalized_banner(self, profile: dict) -> dict:
"""Персонализированный баннер в лобби"""
if profile.get('total_sessions', 0) > 50:
return {'type': 'loyalty_status', 'message': 'VIP игрок — эксклюзивные турниры'}
elif profile.get('top_game_category') == 'live_casino':
return {'type': 'live_tables', 'message': 'Новые live столы уже доступны'}
return {'type': 'general_promo'}
def _select_bonus(self, profile: dict) -> dict:
"""Подбор бонусного предложения под профиль"""
avg_bet = profile.get('avg_bet_size', 10)
category = profile.get('top_game_category', 'slots')
if category == 'sports_betting':
return {'type': 'free_bet', 'amount': round(avg_bet * 5, -1)}
elif category == 'live_casino':
return {'type': 'cashback', 'percentage': 10}
elif avg_bet > 50:
return {'type': 'high_roller_bonus', 'amount': round(avg_bet * 10, -1)}
else:
return {'type': 'free_spins', 'count': 20}
class ResponsibleGamblingMonitor:
"""
Мониторинг признаков проблемного игрового поведения.
ОБЯЗАТЕЛЕН по регуляторным требованиям (MGA, UKGC, Роскомнадзор).
"""
RG_INDICATORS = {
'session_duration_spike': 'Значительный рост длительности сессий',
'deposit_frequency_increase': 'Учащение депозитов',
'loss_chasing': 'Погоня за потерями (рост ставок после проигрыша)',
'time_of_day_shift': 'Ночные сессии (после 01:00)',
'multiple_sessions_per_day': 'Более 3 сессий в день',
}
def compute_rg_risk_score(self, player_behavior: dict) -> dict:
"""Оценка риска проблемного игрового поведения"""
risk_score = 0.0
triggered_indicators = []
if player_behavior.get('avg_session_duration_change_pct', 0) > 50:
risk_score += 0.25
triggered_indicators.append(self.RG_INDICATORS['session_duration_spike'])
if player_behavior.get('deposit_frequency_7d', 0) > 5:
risk_score += 0.20
triggered_indicators.append(self.RG_INDICATORS['deposit_frequency_increase'])
if player_behavior.get('avg_bet_after_loss', 0) > player_behavior.get('avg_normal_bet', 10) * 2:
risk_score += 0.30
triggered_indicators.append(self.RG_INDICATORS['loss_chasing'])
if player_behavior.get('night_session_ratio', 0) > 0.30:
risk_score += 0.15
triggered_indicators.append(self.RG_INDICATORS['time_of_day_shift'])
rg_level = 'high' if risk_score > 0.6 else 'medium' if risk_score > 0.3 else 'low'
return {
'rg_risk_score': round(min(risk_score, 1.0), 2),
'rg_level': rg_level,
'triggered_indicators': triggered_indicators,
'recommended_action': (
'mandatory_interaction' if rg_level == 'high'
else 'soft_limit_suggestion' if rg_level == 'medium'
else 'none'
)
}
Lobby personalization increases session depth (the number of games played per session) by 15-25% and retention rates by 10-15%. A prerequisite: RG monitoring must work in parallel with personalization—increasing engagement and protecting vulnerable players are not in conflict with each other when implemented correctly.







