test(gherkin): ajouter tests BDD pour toutes clarifications règles métier
Ajoute/modifie tests Gherkin pour couvrir les 7 sections clarifiées : 1. Algorithme recommandation (scoring intérêts nuls) : - Ajout scénarios scoring-recommandation.feature - Cas contenu géo-ancré proche avec intérêts nuls = recommandable - Comparaison scores géo vs intérêts 2. Audio-guides mode voiture (système double clic) : - Nouveau fichier systeme-double-clic-sortie.feature - Premier clic : passage mode manuel + séquence suivante - Deuxième clic <10s : sortie audio-guide - Détection hors itinéraire + reprise 3. Monétisation créateurs (soldes dormants + DAS2) : - Nouveau fichier soldes-dormants-inactifs.feature - Conservation indéfinie si actif - Emails 12/18 mois + versement forcé 18 mois + 30j - Exception soldes <10€ avec proposition don - Modification obligations-fiscales.feature - DAS2 systématique tous montants (même <1200€) 4. Skip et abonnement (neutralisation pénalités) : - Nouveau fichier skip-abonnes-neutralisation.feature - Skip <10s non-abonné : -0.5% - Skip <10s abonné : 0% (neutre) - Métriques engagement : abonnés ne pénalisent pas - Anti-raid naturel (sources non pertinentes) 5. Premium multi-devices (KISS) : - Nouveau fichier multi-devices-dernier-priorite.feature - Règle simple : dernier device prend toujours priorité - Offline connecté vs déconnecté - Détection abus post-MVP (pas automatique) 6. Mode offline (contenus supprimés) : - Nouveau fichier contenus-supprimes-pendant-offline.feature - Suppression immédiate à reconnexion - Modal si contenu en cours d'écoute - Popup récapitulative si 2+ contenus supprimés 7. Publicités (ciblage horaire + fuseaux horaires) : - Nouveau fichier ciblage-horaire-fuseaux-horaires.feature - Ciblage horaire = heure locale utilisateur - France entière = Métropole + DOM - Détection fuseau GPS/device/IP - Cas d'usage restaurant Guadeloupe, assureur national Couverture complète de toutes les règles métier clarifiées.
This commit is contained in:
204
features/api/interest-gauges/skip-abonnes-neutralisation.feature
Normal file
204
features/api/interest-gauges/skip-abonnes-neutralisation.feature
Normal file
@@ -0,0 +1,204 @@
|
||||
# language: fr
|
||||
Fonctionnalité: Neutralisation des pénalités de skip pour abonnés
|
||||
En tant que système de jauges d'intérêt
|
||||
Je veux neutraliser les pénalités de skip pour les abonnés d'un créateur
|
||||
Afin de reconnaître l'affinité globale malgré des skips ponctuels contextuels
|
||||
|
||||
Contexte:
|
||||
Étant donné qu'un utilisateur existe avec les jauges suivantes:
|
||||
| catégorie | niveau |
|
||||
| Automobile | 45% |
|
||||
| Voyage | 60% |
|
||||
Et qu'un créateur "CreateurA" publie des contenus tagués "Automobile"
|
||||
|
||||
# Skip <10s - Utilisateur NON abonné
|
||||
|
||||
Scénario: Skip rapide <10s par non-abonné - Pénalité -0.5%
|
||||
Étant donné que l'utilisateur n'est PAS abonné à "CreateurA"
|
||||
Et qu'un contenu "Podcast Auto" de "CreateurA" est tagué "Automobile"
|
||||
Et que la jauge "Automobile" est à 45%
|
||||
Quand l'utilisateur skip le contenu après 5 secondes
|
||||
Alors la jauge "Automobile" descend de -0.5%
|
||||
Et la jauge "Automobile" passe de 45% à 44.5%
|
||||
Et cela indique un désintérêt marqué pour ce contenu
|
||||
|
||||
Scénario: Skip rapide <10s par non-abonné - Colonne is_subscribed=false
|
||||
Étant donné que l'utilisateur n'est PAS abonné à "CreateurA"
|
||||
Et qu'un contenu est skippé après 8 secondes
|
||||
Quand l'événement est enregistré dans user_listening_history
|
||||
Alors la colonne is_subscribed = false
|
||||
Et la colonne completion_rate = 0.05 (8s sur 160s)
|
||||
Et la colonne source = "recommendation"
|
||||
Et ce skip compte dans les métriques d'engagement du contenu
|
||||
|
||||
# Skip <10s - Utilisateur ABONNÉ
|
||||
|
||||
Scénario: Skip rapide <10s par abonné - Pénalité neutre 0%
|
||||
Étant donné que l'utilisateur EST abonné à "CreateurA"
|
||||
Et qu'un contenu "Podcast Auto" de "CreateurA" est tagué "Automobile"
|
||||
Et que la jauge "Automobile" est à 45%
|
||||
Quand l'utilisateur skip le contenu après 5 secondes
|
||||
Alors la jauge "Automobile" reste à 45% (pénalité 0%)
|
||||
Et aucune pénalité n'est appliquée
|
||||
Et cela reflète que l'abonnement indique une affinité globale
|
||||
|
||||
Scénario: Skip rapide <10s par abonné - Colonne is_subscribed=true
|
||||
Étant donné que l'utilisateur EST abonné à "CreateurA"
|
||||
Et qu'un contenu est skippé après 7 secondes
|
||||
Quand l'événement est enregistré dans user_listening_history
|
||||
Alors la colonne is_subscribed = true
|
||||
Et la colonne completion_rate = 0.04 (7s sur 180s)
|
||||
Et la colonne source = "recommendation"
|
||||
Et ce skip NE compte PAS dans les métriques d'engagement du contenu
|
||||
|
||||
# Calcul métriques engagement créateur
|
||||
|
||||
Scénario: Métriques engagement - Skip d'abonné ne pénalise pas
|
||||
Étant donné qu'un contenu "Podcast A" de "CreateurA" a reçu:
|
||||
| utilisateur | abonné ? | action | source | completion_rate |
|
||||
| User1 | Non | Skip <10s | recommendation | 0.05 |
|
||||
| User2 | Oui | Skip <10s | recommendation | 0.04 |
|
||||
| User3 | Non | Écoute complète | recommendation | 0.90 |
|
||||
| User4 | Oui | Skip <10s | recommendation | 0.03 |
|
||||
| User5 | Non | Écoute partielle | recommendation | 0.60 |
|
||||
Quand le système calcule les métriques d'engagement du contenu
|
||||
Alors les écoutes pertinentes comptabilisées sont:
|
||||
| utilisateur | comptabilisé ? | raison |
|
||||
| User1 | ✅ Oui | Non-abonné, source pertinente |
|
||||
| User2 | ❌ Non | Abonné, skip contextuel |
|
||||
| User3 | ✅ Oui | Non-abonné, source pertinente |
|
||||
| User4 | ❌ Non | Abonné, skip contextuel |
|
||||
| User5 | ✅ Oui | Non-abonné, source pertinente |
|
||||
Et le total écoutes pertinentes = 3 (User1, User3, User5)
|
||||
Et le taux de complétion = 2 complètes (User3, User5 >80%) / 3 = 66.7%
|
||||
|
||||
# Sources d'écoute et neutralisation
|
||||
|
||||
Scénario: Skip d'abonné via "recommendation" - Ne compte pas
|
||||
Étant donné que l'utilisateur EST abonné à "CreateurA"
|
||||
Et qu'un contenu est recommandé via l'algorithme (source="recommendation")
|
||||
Quand l'utilisateur skip après 5s
|
||||
Alors l'écoute NE compte PAS dans "total écoutes" pour métriques
|
||||
Et la pénalité jauge est neutralisée (0%)
|
||||
|
||||
Scénario: Skip d'abonné via "live_notification" - Ne compte pas
|
||||
Étant donné que l'utilisateur EST abonné à "CreateurA"
|
||||
Et que "CreateurA" publie un contenu en live
|
||||
Et qu'une notification live est envoyée (source="live_notification")
|
||||
Quand l'utilisateur skip après 6s
|
||||
Alors l'écoute NE compte PAS dans "total écoutes" pour métriques
|
||||
Et la pénalité jauge est neutralisée (0%)
|
||||
|
||||
Scénario: Skip d'abonné via "search" - Ne compte pas (indépendamment abonnement)
|
||||
Étant donné que l'utilisateur EST abonné à "CreateurA"
|
||||
Et qu'il trouve un contenu via la recherche (source="search")
|
||||
Quand l'utilisateur skip après 4s
|
||||
Alors l'écoute NE compte PAS dans "total écoutes" (source non pertinente)
|
||||
Et la pénalité jauge est neutralisée (0%)
|
||||
Et cela s'applique à tous users (abonnés ou non) pour source="search"
|
||||
|
||||
Scénario: Skip non-abonné via "direct_link" - Ne compte pas
|
||||
Étant donné que l'utilisateur N'est PAS abonné à "CreateurA"
|
||||
Et qu'il clique sur un lien direct partagé (source="direct_link")
|
||||
Quand l'utilisateur skip après 3s
|
||||
Alors l'écoute NE compte PAS dans "total écoutes" (source non pertinente)
|
||||
Mais la pénalité jauge s'applique quand même (-0.5%) pour non-abonné
|
||||
|
||||
# Reproposition
|
||||
|
||||
Scénario: Skip <10s non-abonné - Pas de reproposition
|
||||
Étant donné que l'utilisateur N'est PAS abonné à "CreateurA"
|
||||
Et qu'un contenu est skippé après 8 secondes
|
||||
Quand l'algorithme calcule les prochaines recommandations
|
||||
Alors ce contenu n'est jamais reproposé à cet utilisateur
|
||||
Car c'est un signal négatif clair de désintérêt
|
||||
|
||||
Scénario: Skip <10s abonné - Reproposition possible
|
||||
Étant donné que l'utilisateur EST abonné à "CreateurA"
|
||||
Et qu'un contenu est skippé après 7 secondes
|
||||
Quand l'algorithme calcule les prochaines recommandations plusieurs jours plus tard
|
||||
Alors ce contenu PEUT être reproposé à cet utilisateur
|
||||
Car l'abonnement indique une affinité globale
|
||||
Et le skip peut être contextuel ("pas maintenant", "pas ce sujet")
|
||||
|
||||
Scénario: Stockage is_subscribed dans user_content_history
|
||||
Étant donné qu'un utilisateur EST abonné à "CreateurA" au moment de l'écoute
|
||||
Quand un contenu de "CreateurA" est écouté/skippé
|
||||
Alors la table user_content_history enregistre:
|
||||
| colonne | valeur |
|
||||
| user_id | 123 |
|
||||
| content_id | 456 |
|
||||
| creator_id | 789 (CreateurA) |
|
||||
| is_subscribed | true |
|
||||
| completion_rate| 0.05 |
|
||||
| source | "recommendation" |
|
||||
| listened_at | 2026-02-07 10:30:00 |
|
||||
|
||||
# Cohérence UX
|
||||
|
||||
Scénario: Abonnement = Signal affinité fort malgré skip ponctuel
|
||||
Étant donné que l'utilisateur est abonné à "CreateurA" depuis 6 mois
|
||||
Et qu'il a écouté 50 contenus de "CreateurA" avec 90% de complétion moyenne
|
||||
Quand il skip 1 contenu après 5 secondes aujourd'hui
|
||||
Alors ce skip ponctuel ne pénalise pas:
|
||||
| aspect | impact |
|
||||
| Jauges d'intérêt user | 0% (neutre) |
|
||||
| Métriques engagement créateur | Ne compte pas dans total écoutes |
|
||||
| Reproposition future | Contenu peut être reproposé |
|
||||
Et cela reflète que le skip est contextuel, pas un rejet du créateur
|
||||
|
||||
# Anti-raid naturel
|
||||
|
||||
Scénario: Raid malveillant via liens directs - Inefficace
|
||||
Étant donné qu'un groupe malveillant veut nuire à "CreateurA"
|
||||
Et qu'ils partagent des liens directs pour inciter au skip massif
|
||||
Quand 1000 personnes cliquent sur le lien et skip après 2s
|
||||
Alors ces 1000 skips NE comptent PAS dans les métriques engagement
|
||||
Car source="direct_link" n'est pas une source pertinente
|
||||
Et "CreateurA" est protégé contre ce type de raid
|
||||
|
||||
Scénario: Raid malveillant via recherche - Inefficace
|
||||
Étant donné qu'un groupe cherche à nuire à "CreateurA"
|
||||
Et qu'ils trouvent le contenu via recherche et skip massivement
|
||||
Quand 500 skips rapides arrivent via source="search"
|
||||
Alors ces 500 skips NE comptent PAS dans les métriques engagement
|
||||
Car source="search" n'est pas une source pertinente
|
||||
Et "CreateurA" est protégé
|
||||
|
||||
# Cas limites
|
||||
|
||||
Scénario: Utilisateur s'abonne pendant l'écoute d'un contenu
|
||||
Étant donné qu'un utilisateur N'est PAS abonné à "CreateurA"
|
||||
Et qu'il démarre l'écoute d'un contenu de "CreateurA"
|
||||
Et que is_subscribed=false est enregistré au démarrage
|
||||
Quand l'utilisateur s'abonne à "CreateurA" pendant l'écoute
|
||||
Et qu'il skip le contenu après 8 secondes
|
||||
Alors is_subscribed=false reste enregistré (état au moment du démarrage)
|
||||
Et la pénalité -0.5% s'applique (car non-abonné au démarrage)
|
||||
|
||||
Scénario: Utilisateur se désabonne puis écoute ancien contenu
|
||||
Étant donné qu'un utilisateur ÉTAIT abonné à "CreateurA"
|
||||
Et qu'il se désabonne aujourd'hui
|
||||
Quand il écoute un ancien contenu de "CreateurA" demain
|
||||
Et qu'il skip après 6 secondes
|
||||
Alors is_subscribed=false (état au moment de l'écoute)
|
||||
Et la pénalité -0.5% s'applique
|
||||
Et l'écoute compte dans les métriques d'engagement
|
||||
|
||||
# Comparaison tableaux sources
|
||||
|
||||
Scénario: Table récapitulative sources et abonnements
|
||||
Étant donné les règles de comptabilisation définies
|
||||
Quand on résume le comportement par source et abonnement
|
||||
Alors le tableau complet est:
|
||||
| Source | Abonné ? | Skip <10s pénalise ? | Compte "total écoutes" ? |
|
||||
| recommendation | Non | ✅ Oui (-0.5%) | ✅ Oui |
|
||||
| recommendation | Oui | ❌ Non (0%) | ❌ Non |
|
||||
| search | Peu imp. | Variable* | ❌ Non |
|
||||
| direct_link | Peu imp. | Variable* | ❌ Non |
|
||||
| profile | Peu imp. | Variable* | ❌ Non |
|
||||
| history | Peu imp. | Variable* | ❌ Non |
|
||||
| live_notification | Non | ✅ Oui (-0.5%) | ✅ Oui |
|
||||
| live_notification | Oui | ❌ Non (0%) | ❌ Non |
|
||||
| audio_guide | Peu imp. | ❌ Non | ❌ Non |
|
||||
(* Variable = -0.5% si non-abonné, 0% si abonné, mais source non pertinente donc pas dans métriques)
|
||||
Reference in New Issue
Block a user