Ajout section détaillée "Calcul score_interets" dans Règle 04: - Domaine jauges : [0-100] (stockage en pourcentage) - score_interets : [0.0-1.0] (normalisé pour pondération) - Formule exacte : (SUM(gauges) / NB_TAGS) / 100 Exemple concret avec nombres : - Tags ["Musique", "Tourisme"] - Jauges utilisateur 75% et 60% - score_interets = 0.675 - Impact dans score_final démontré Cas limites documentés : - Aucune jauge → valeur neutre 0.5 - 1 seul tag → gauge_value / 100 - Moyenne arithmétique simple (pas de pondération par tag) Résout incohérence #1 (INCONSISTENCIES.md P0 item 4). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
13 KiB
2. Algorithme de recommandation
2.1 Classification de géo-pertinence
Décision : 3 types de contenus selon leur pertinence géographique
| Type | Description | Exemple | Pondération géo |
|---|---|---|---|
| Géo-ancré | Contenu lié à un lieu précis | Audio-guide monument, pub restaurant local | 70% |
| Géo-contextuel | Pertinent dans une zone | Actualité régionale, événement local | 50% |
| Géo-neutre | Universel, pas de lien géo | Podcast philosophie, musique | 20% |
Qui décide :
- ✅ Créateur choisit le type à la publication
- ✅ Modération peut reclassifier après validation
- ✅ Modification possible après publication (tout le monde a le droit de se tromper)
Justification :
- Différencie audio-guide (hyper-local) des podcasts génériques
- Algorithme adapte automatiquement la pondération
- Coût : champ supplémentaire en DB + règle algo
2.2 Formule de scoring
Décision : Score combiné dynamique selon type de contenu
score_final = (score_geo * poids_geo_type)
+ (score_interets * poids_interets_type)
+ (score_engagement * 0.2)
+ (bonus_aleatoire)
où :
- score_geo = 1 - (distance_km / distance_max_km)
- score_interets = moyenne des jauges utilisateur pour les tags du contenu
- score_engagement = (taux_completion * 0.5) + (ratio_likes * 0.3) + (ratio_abonnements * 0.2)
- bonus_aleatoire = 10% des recommandations tirées aléatoirement
Calcul détaillé du score_interets
Domaine des données :
- Jauges utilisateur : stockées en pourcentage [0-100]
- score_interets : normalisé dans l'intervalle [0.0-1.0] pour pondération
Formule exacte :
score_interets = (SUM(gauge_values_for_tags) / NB_TAGS) / 100
où :
- gauge_values_for_tags = valeurs des jauges correspondant aux tags du contenu
- NB_TAGS = nombre de tags du contenu (minimum 1, maximum 3)
- Division par 100 pour normaliser [0-100] → [0.0-1.0]
Exemple concret :
Contenu : "Visite du Louvre"
Tags : ["Musique", "Tourisme"]
Utilisateur :
- Jauge "Musique" = 75%
- Jauge "Tourisme" = 60%
- Jauge "Automobile" = 40% (non pertinente, ignorée)
Calcul :
score_interets = ((75 + 60) / 2) / 100
= (135 / 2) / 100
= 67.5 / 100
= 0.675
Impact dans le scoring final (type géo-contextuel) :
score_final = (score_geo * 0.5) + (score_interets * 0.3) + (score_engagement * 0.2) + bonus_aleatoire
= (0.8 * 0.5) + (0.675 * 0.3) + (0.5 * 0.2) + 0
= 0.4 + 0.2025 + 0.1
= 0.7025 / 1.0
Cas limites :
- Utilisateur n'a aucune jauge pour les tags du contenu → score_interets = 0.5 (valeur neutre par défaut)
- Contenu avec 1 seul tag → score_interets = gauge_value / 100
- Jauges multiples → moyenne arithmétique simple (pas de pondération différente par tag)
Pondérations par type :
| Type | Poids géo | Poids intérêts |
|---|---|---|
| Géo-ancré | 0.7 | 0.1 |
| Géo-contextuel | 0.5 | 0.3 |
| Géo-neutre | 0.2 | 0.6 |
Paramètres :
- Distance max recommandée : 200 km
- Dégradation : linéaire (1 - distance/200km)
- Rayon point GPS : 500m (adapté au volume de contenu local)
Tous ces paramètres sont configurables à chaud via interface admin.
Justification :
- Flexibilité totale selon type de contenu
- Linéaire = rattrapage naturel du contenu viral ancien
- Auditable via métriques engagement (moyenne/médiane)
2.3 Score d'engagement et popularité
Décision : Intégration popularité avec poids 0.2
Métriques :
- Taux de complétion : écoutes >80% / total écoutes (poids 0.5)
- Ratio likes : likes / écoutes (poids 0.3)
- Ratio abonnements : nouveaux abonnés après écoute / écoutes (poids 0.2)
Seuil minimum :
- Minimum 50 écoutes avant de considérer l'engagement
- Contenu <50 écoutes : score engagement = 0.5 (neutre)
Contenu viral :
- Un contenu viral à Paris peut être proposé à Marseille
- Score géo faible compensé par score engagement élevé
- Paramétrable admin
Dépréciation temporelle :
- Pas de dépréciation automatique
- Ratio linéaire = contenu ancien mais toujours apprécié reste pertinent
Justification :
- Équilibre découverte / qualité
- Pas de pénalisation arbitraire des contenus anciens
- Coût : calculs sur métriques existantes
2.4 Part d'aléatoire (exploration)
Décision : 10% par défaut, paramétrable utilisateur
Fonctionnement :
- 1 contenu sur 10 = tirage aléatoire (hors historique déjà écouté)
- Utilisateur peut ajuster : curseur 0% (aucun aléatoire) à 50% (exploration max)
Curseur utilisateur :
- 🎯 0% : Personnalisé max (recommandations strictes)
- ⚖️ 10% : Équilibré (défaut)
- 🎲 30% : Découverte élevée
- 🌍 50% : Découverte max (équivaut à national = découverte)
Justification :
- Évite la bulle de filtre
- Laisse l'utilisateur maître de son expérience
- Coût : variable aléatoire en algo
2.5 Contenu politique (version MVP simplifiée)
⚠️ Note : La classification politique avancée (échelle gauche/droite, équilibrage imposé) a été reportée post-MVP. Voir ANNEXE-POST-MVP.md pour la version complète.
Décision MVP : Tag simple "Politique" sans classification idéologique
Tagging :
- Créateur peut taguer son contenu comme "Politique" (optionnel)
- Tag "Politique" au même niveau que "Économie", "Sport", "Culture", etc.
- Pas de classification gauche/droite
- Pas d'équilibrage imposé
Filtrage utilisateur :
- Option paramètres : "Masquer contenu politique"
- Si activé → 0% de contenus tagués "Politique" dans le feed
- Par défaut : désactivé (tous contenus visibles)
Justification MVP :
- Simplicité : Pas de modération politique coûteuse (~2000€/mois économisés)
- Neutralité technique : Aucun jugement éditorial sur orientation
- Risque minimal : Évite controverses et contentieux DSA au lancement
- Fonctionnel : Utilisateurs peuvent filtrer si souhaité
Post-MVP :
- Classification avancée possible si forte demande utilisateurs
- Nécessite ressources modération dédiées et audit DSA
2.6 Mode Kids (13-15 ans)
Décision : Mode optionnel pour adolescents 13-15 ans uniquement
⚠️ Note : Âge minimum d'inscription = 13 ans (obligation légale EU). Pas d'utilisateurs <13 ans sur la plateforme.
Tranche concernée :
| Tranche | Description | Contenus autorisés | Restrictions |
|---|---|---|---|
| 13-15 ans | Collège | Contenus "Tous publics" uniquement | Filtrage 16+ et 18+ |
Activation :
- ❌ Pas d'activation automatique (tous les utilisateurs ont ≥13 ans)
- ✅ Activation manuelle via toggle paramètres
- ✅ Parents peuvent activer pour leurs enfants 13-15 ans
- ✅ Utilisateur peut désactiver à tout moment
Filtrage quand Mode Kids activé :
- ✅ Contenus "Tous publics" uniquement
- ❌ Exclusion contenus 16+ et 18+
- ❌ Pas de contenu politique (automatiquement filtré)
- ❌ Pas de publicité (ou uniquement pub validée manuellement)
Interface :
- Interface standard (pas d'interface dédiée enfants pour MVP)
- Filtrage algorithmique des contenus inappropriés
Justification :
- Conformité légale : Âge minimum 13 ans (RGPD, DSA)
- Simplicité MVP : Un seul mode optionnel vs 4 tranches d'âge
- Protection mineurs : Filtrage contenus adultes pour 13-15 ans
- Flexibilité : Parents décident d'activer ou non
2.7 Déclenchement géographique
Décision : Notification au passage, pas d'anticipation
Fonctionnement :
- Utilisateur passe à <500m d'un point GPS (contenu géo-ancré)
- Notification sonore (bip court) + visuelle (logo selon type)
- Types de logos : 📍 Info, 🏛️ Culturel, 🍴 Commercial, 🎭 Événement
- Délai réaction utilisateur : 5 secondes pour accepter (bouton volant ou commande vocale)
- Si accepté → lecture immédiate
- Si ignoré → contenu proposé normalement en file d'attente
Publicités :
- ⚠️ Jamais d'interruption de contenu en cours
- Pub s'intercale entre deux séquences uniquement
- Notification pub : son différent (facultatif selon paramètres)
Gestion demi-tour :
- Si utilisateur repart du point après notification → pas de nouvelle notification (déjà proposé)
- Réinitialisation après 24h
Justification :
- Respect écoute en cours (pas de coupure brutale)
- UX fluide (utilisateur garde contrôle)
- Simplicité technique (pas de prédiction trajectoire)
2.8 Historique et repropositon
Décision : Pas de reproposition sauf contenu partiel
Règles :
| État écoute | Completion | Action |
|---|---|---|
| Écouté complètement | >80% | ❌ Ne jamais reproposer (sauf flag replayable = true pour audio-guides) |
| Skippé rapidement | <10s | ❌ Ne pas reproposer |
| Partiellement écouté | 10-80% | ✅ Reproposer avec reprise position (last_position_seconds) |
Stockage historique :
- Table
user_content_history(user_id, content_id, completion_rate, last_position, listened_at) - Historique illimité (PostgreSQL)
- Algorithme considère les 100 derniers pour optimisation requêtes
- Export complet disponible (RGPD)
Justification :
- Découverte maximale (pas de redites)
- Respect erreurs de clic (contenu partiel = 2nde chance)
- Coût stockage négligeable (PostgreSQL scalable)
2.9 Paramétrabilité admin (interface dashboard)
Décision : Tous paramètres scoring exposés + A/B testing
Paramètres configurables à chaud :
| Paramètre | Plage | Défaut | Unité |
|---|---|---|---|
poids_geo_ancre |
0.5 - 1.0 | 0.7 | % |
poids_geo_contextuel |
0.3 - 0.7 | 0.5 | % |
poids_geo_neutre |
0.0 - 0.4 | 0.2 | % |
poids_engagement |
0.0 - 0.5 | 0.2 | % |
part_aleatoire_global |
0.0 - 0.3 | 0.1 | % |
distance_max_km |
50 - 500 | 200 | km |
rayon_gps_point_m |
100 - 2000 | 500 | m |
seuil_min_ecoutes_engagement |
10 - 200 | 50 | nb |
Application changements :
- Immédiat : nouveaux calculs utilisent nouvelle config
- Aucun recalcul batch (coût CPU)
- Version config trackée (git-like)
- Rollback 1 clic
A/B Testing :
- Création variantes (Config A vs Config B)
- Split utilisateurs 50/50 aléatoire
- Métriques comparatives : taux complétion, engagement, session duration
- Dashboard graphique temps réel
Audit engagement :
- Métriques clés : moyenne/médiane temps d'écoute par session
- Graphiques : évolution engagement selon config
- Export CSV pour analyse externe
Justification :
- Optimisation continue sans redéploiement
- Data-driven decisions (métriques objectives)
- Coût : dashboard admin à développer (one-time)
2.10 Paramétrabilité utilisateur
Décision : Curseurs avancés avec profils sauvegardables
Niveaux de personnalisation :
Curseurs disponibles :
- 📍 Géolocalisation : Local ← slider → National (découverte = national)
- 🎲 Découverte : 0% ← slider → 50% (part aléatoire)
- ⚖️ Politique : Masquer / Équilibré / Mes préférences
Profils sauvegardables :
- 🚗 Trajet quotidien (boulot) : géo local, découverte 5%, politique masqué
- 🛣️ Road trip : géo régional, découverte 30%, politique équilibré
- 👶 Enfants : Mode Kids activé
Synchronisation :
- ✅ Sync profils entre devices (cloud PostgreSQL)
- ❌ Pas de partage profils entre utilisateurs (famille)
- Auto-switch selon context (détection trajet récurrent via GPS)
Sécurité conduite :
- ⚠️ Blocage modification si vitesse GPS >10 km/h
- Warning au lancement app : "Configurez avant de prendre la route"
- Modifications uniquement app arrêtée/passager
Justification :
- Utilisateur maître de son expérience
- Contextes d'usage différents (quotidien vs voyage)
- Sécurité routière (pas de distraction)
2.11 Médias traditionnels
Décision : Ouverture aux médias établis
Médias autorisés :
- Presse nationale : Le Monde, Le Parisien, Libération, Le Figaro, etc.
- Radios : France Inter, RTL, Europe 1, etc.
- Médias régionaux : Ouest-France, Sud-Ouest, etc.
Format contenus :
- Flashs info géolocalisés (actualité régionale)
- Chroniques thématiques (culture, économie, sport)
- Éditos et débats (classification politique appliquée)
Validation :
- Compte média vérifié (badge ✓)
- Pas de validation 3 premiers contenus (confiance établie)
- Modération a posteriori uniquement
Monétisation :
- Partage revenus pub standard (même conditions créateurs)
- Possibilité sponsoring direct (pas via plateforme)
Justification :
- Crédibilité plateforme (contenus professionnels)
- Diversité éditoriale
- Attractivité grand public (noms reconnus)