AI iGaming Experience Personalization System

We design and deploy artificial intelligence systems: from prototype to production-ready solutions. Our team combines expertise in machine learning, data engineering and MLOps to make AI work not in the lab, but in real business.
Showing 1 of 1 servicesAll 1566 services
AI iGaming Experience Personalization System
Medium
~2-4 weeks
FAQ
AI Development Areas
AI Solution Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1212
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822

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.