|
1 |
+<!DOCTYPE html> |
|
2 |
+<!-- |
|
3 |
+ DraftVision 2027 — Plateforme de prévision du repêchage LNH 2027 |
|
4 |
+ Auteur : Simon-Pierre Boucher — contact@spboucher.ai |
|
5 |
+ Données : pipeline de recherche web du 2026-08-08 (voir RECHERCHE.md) |
|
6 |
+--> |
|
7 |
+<html lang="fr"> |
|
8 |
+<head> |
|
9 |
+<meta charset="UTF-8"> |
|
10 |
+<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
11 |
+<title>DraftVision 2027 — Prévision du repêchage LNH 2027</title> |
|
12 |
+<link rel="preconnect" href="https://fonts.googleapis.com"> |
|
13 |
+<link href="https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@500;600;700&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"> |
|
14 |
+<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script> |
|
15 |
+<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script> |
|
16 |
+<script src="https://unpkg.com/@babel/standalone@7.26.4/babel.min.js"></script> |
|
17 |
+<style> |
|
18 |
+ :root{ |
|
19 |
+ --fond:#0A0E1A; --panneau:#111827; --panneau2:#0D1322; --bordure:#1F2A3F; |
|
20 |
+ --glace:#4FC3F7; --vert:#22C55E; --rouge:#EF4444; --ambre:#F59E0B; |
|
21 |
+ --texte:#E5EAF2; --texte2:#93A1B8; --texte3:#5C6B84; |
|
22 |
+ } |
|
23 |
+ *{box-sizing:border-box; margin:0; padding:0;} |
|
24 |
+ html{scroll-behavior:smooth;} |
|
25 |
+ body{background:var(--fond); color:var(--texte); font-family:'Inter',system-ui,sans-serif; font-size:14px; line-height:1.5;} |
|
26 |
+ h1,h2,h3,.titre{font-family:'Barlow Condensed',sans-serif; letter-spacing:.02em;} |
|
27 |
+ .num{font-variant-numeric:tabular-nums;} |
|
28 |
+ button{font-family:inherit; cursor:pointer;} |
|
29 |
+ input,select{font-family:inherit;} |
|
30 |
+ ::-webkit-scrollbar{width:10px;height:10px;} |
|
31 |
+ ::-webkit-scrollbar-track{background:var(--fond);} |
|
32 |
+ ::-webkit-scrollbar-thumb{background:var(--bordure); border-radius:5px;} |
|
33 |
+ @keyframes apparait{from{opacity:0; transform:translateY(6px);} to{opacity:1; transform:none;}} |
|
34 |
+ @keyframes pulse-glace{0%,100%{box-shadow:0 0 0 0 rgba(79,195,247,.35);} 50%{box-shadow:0 0 0 8px rgba(79,195,247,0);}} |
|
35 |
+ .apparait{animation:apparait .25s ease both;} |
|
36 |
+ a{color:var(--glace);} |
|
37 |
+ button:focus-visible, input:focus-visible, select:focus-visible, [tabindex]:focus-visible{outline:2px solid var(--glace); outline-offset:2px;} |
|
38 |
+</style> |
|
39 |
+</head> |
|
40 |
+<body> |
|
41 |
+<div id="racine"></div> |
|
42 |
+<script type="text/babel" data-presets="react"> |
|
43 |
+const {useState, useMemo, useRef, useEffect, useCallback} = React; |
|
44 |
+ |
|
45 |
+/* ============================================================ |
|
46 |
+ DONNÉES — issues du pipeline de recherche web du 2026-08-08 |
|
47 |
+ (Phases A→F, voir RECHERCHE.md). Aucune donnée inventée : |
|
48 |
+ ce qui est introuvable est null / « n.d. ». |
|
49 |
+ ============================================================ */ |
|
50 |
+ |
|
51 |
+const META = { |
|
52 |
+ dateGeneration: "2026-08-08", |
|
53 |
+ dateDonnees: "2026-08-08", |
|
54 |
+ phasesCompletees: ["A","B","C","D","E","F"], |
|
55 |
+ avertissements: [ |
|
56 |
+ "La saison LNH 2026-27 n'a pas commencé : l'ordre de sélection est SIMULÉ à partir du classement final 2025-26 (le vrai ordre 2027 dépendra de la saison 2026-27 et de la loterie de mai 2027).", |
|
57 |
+ "La loterie 2027 n'a pas eu lieu — probabilités selon la table officielle 2026 (Daily Faceoff, avril 2026) ; cotes des rangs 12-16 : n.d.", |
|
58 |
+ "Tous les classements d'espoirs sont « way-too-early » (mars-juillet 2026) et changeront fortement d'ici juin 2027.", |
|
59 |
+ "Date, lieu et format du repêchage 2027 : non annoncés en date du 2026-08-08 (format décentralisé probable — reconduit en 2025 et 2026, soutien des clubs confirmé par Bill Daly). Nouveauté CBA 2026-2030 qui débute avec le repêchage 2027 : rétention des droits standardisée (18 ans → 4 ans de droits ; 19 ans+ → 3 ans ; exception NCAA maintenue). L'âge d'admissibilité reste 18 ans. Détails : ADMIN-REPECHAGE-2027.md.", |
|
60 |
+ "Portée réduite : 1re ronde seulement (32 choix). Pas assez de sources fiables pour projeter une 2e ronde, et aucun gardien n'est classé par les sources consultées.", |
|
61 |
+ "Statistiques affichées : saison 2025-26 (dernière saison complète). Le +/- et les statistiques de gardiens sont rarement publiés → « n.d. ».", |
|
62 |
+ "Coupe Hlinka-Gretzky 2026 (Edmonton, 3-8 août — Canada 8-1 USA en finale) : intégrée au calcul via des ajustements bornés (±3 rangs max) appliqués au consensus pondéré, appuyés sur le tableau statistique OFFICIEL du tournoi (Elite Prospects, saison 2026-27, consulté le 8 août — les matchs de médailles du jour n'y sont que partiellement reflétés, complétés par les comptes rendus TSN/PC, Sportsnet, CHL.ca, Daily Faceoff). Bonus ET malus documentés : ex. Joseph +1,0 rang (production discrète, 43e pointeur), England −1,5 (2 buts en finale). Le revers collectif du groupe NTDP américain (8-1, tirs 45-17) est signalé sans pénalité chiffrée supplémentaire." |
|
63 |
+ ] |
|
64 |
+}; |
|
65 |
+ |
|
66 |
+// Pondération renormalisée : les 7 sources prescrites sauf The Athletic n'ont |
|
67 |
+// rien publié pour 2027 (Central Scouting, McKenzie, EP, FCHockey, Dobber, |
|
68 |
+// McKeen's → retirées, poids redistribués sur les classements réels trouvés). |
|
69 |
+const SOURCES = [ |
|
70 |
+ {cle:"wheeler", nom:"The Athletic — Scott Wheeler", date:"2026-03-31", poids:30}, |
|
71 |
+ {cle:"dfo", nom:"Daily Faceoff — Steven Ellis", date:"2026-07-02", poids:25}, |
|
72 |
+ {cle:"tank", nom:"Tankathon (Big Board 2027)", date:"2026-07 (approx.)", poids:20}, |
|
73 |
+ {cle:"thn", nom:"The Hockey News (top 10)", date:"2026-06-28", poids:10}, |
|
74 |
+ {cle:"br", nom:"Bleacher Report (top 10)", date:"2026-07-10", poids:10}, |
|
75 |
+ {cle:"button", nom:"TSN — Craig Button (aperçu pré-saison)", date:"2025-11-07", poids:5}, |
|
76 |
+]; |
|
77 |
+const SOURCES_NON_PUBLIEES = [ |
|
78 |
+ "Bureau central de recrutement LNH (liste préliminaire attendue à l'automne 2026)", |
|
79 |
+ "Bob McKenzie/TSN (ne publie plus depuis 2025)", |
|
80 |
+ "Elite Prospects (liste de surveillance non classée seulement)", |
|
81 |
+ "FCHockey", "Dobber Prospects", "McKeen's Hockey", "The Athletic — Corey Pronman" |
|
82 |
+]; |
|
83 |
+ |
|
84 |
+// Couleurs = palettes officielles approximatives (aucun logo utilisé). |
|
85 |
+// banque = synthèse du classement des banques d'espoirs de Scott Wheeler |
|
86 |
+// (The Athletic, mars-avril 2026), corrigée qualitativement post-repêchage 2026. |
|
87 |
+const EQUIPES = { |
|
88 |
+ ANA:{nom:"Ducks d'Anaheim", c1:"#F47A38", c2:"#B9975B", pool:14, banque:{forces:"McQueen (en santé) parmi les meilleurs espoirs attaquants; bons espoirs en défense (Luneau, Solberg).", lacunes:"Peu d'élite derrière McQueen; profondeur de gardiens moyenne."}}, |
|
89 |
+ BOS:{nom:"Bruins de Boston", c1:"#FFB81C", c2:"#000000", pool:19, banque:{forces:"Hagens en tête; bond de 11 rangs grâce au repêchage 2025.", lacunes:"Défense et gardiens encore minces."}}, |
|
90 |
+ BUF:{nom:"Sabres de Buffalo", c1:"#003087", c2:"#FFB81C", pool:13, banque:{forces:"Positions premium garnies (Mrtka, Helenius, Östlund) + Rudolph (4e, 2026).", lacunes:"Aucun véritable espoir ailier."}}, |
|
91 |
+ CGY:{nom:"Flames de Calgary", c1:"#D2001C", c2:"#FAAF19", pool:3, banque:{forces:"Parekh (D élite), Reschny, Gridin + Carels (6e, 2026).", lacunes:"Pas d'espoir attaquant vedette de calibre no 1."}}, |
|
92 |
+ CAR:{nom:"Hurricanes de la Caroline", c1:"#CE1126", c2:"#76232F", pool:21, banque:{forces:"Volume (18 espoirs classés), succès dans les rondes intermédiaires et chez les Russes.", lacunes:"Pas de vedette; un seul choix de 1re ronde dans le groupe."}}, |
|
93 |
+ CHI:{nom:"Blackhawks de Chicago", c1:"#CF0A2C", c2:"#FF671B", pool:1, banque:{forces:"Meilleure banque de la LNH (Wheeler) : espoirs de premier plan partout, 8 choix de 1re ronde dans le pool.", lacunes:"Il manque surtout un espoir « élite » consensuel."}}, |
|
94 |
+ COL:{nom:"Avalanche du Colorado", c1:"#6F263D", c2:"#236192", pool:28, banque:{forces:"Le top-5 du pool (Brindley, Nabokov, Gulyayev, Behrens) est solide.", lacunes:"Peu de choix récents; profondeur limitée."}}, |
|
95 |
+ CBJ:{nom:"Blue Jackets de Columbus", c1:"#002654", c2:"#CE1126", pool:17, banque:{forces:"Smith (D) et Andreyanov (G) en tête; bonne banque de gardiens.", lacunes:"Chute de 11 rangs (blessure de Lindstrom, graduations, échanges)."}}, |
|
96 |
+ DAL:{nom:"Stars de Dallas", c1:"#006847", c2:"#8F8F8C", pool:31, banque:{forces:"Deux ailiers talentueux mais imparfaits (Hemming, Schmidt).", lacunes:"Seulement 8 espoirs classés; besoin criant partout."}}, |
|
97 |
+ DET:{nom:"Red Wings de Détroit", c1:"#CE1126", c2:"#FFFFFF", pool:4, banque:{forces:"Deux des meilleurs gardiens espoirs hors LNH (Cossa, Augustine); Sandin-Pellikka.", lacunes:"Manque un attaquant « game-breaker »."}}, |
|
98 |
+ EDM:{nom:"Oilers d'Edmonton", c1:"#041E42", c2:"#FF4C00", pool:30, banque:{forces:"Ike Howard en tête; Akey en défense.", lacunes:"Parmi les banques les plus pauvres depuis des années."}}, |
|
99 |
+ FLA:{nom:"Panthers de la Floride", c1:"#041E42", c2:"#C8102E", pool:32, banque:{forces:"Quelques espoirs à surveiller (Devine, Alscher, Gerasimyuk).", lacunes:"Armoires vides : 4 repêchages consécutifs sans choix de 1re ronde."}}, |
|
100 |
+ LAK:{nom:"Kings de Los Angeles", c1:"#111111", c2:"#A2AAAD", pool:27, banque:{forces:"3 solides espoirs D et 2 bons gardiens (George, Slukynsky).", lacunes:"Trou béant au centre; pas d'espoir vedette."}}, |
|
101 |
+ MIN:{nom:"Wild du Minnesota", c1:"#154734", c2:"#A6192E", pool:23, banque:{forces:"La classe 2025 entre dans les classements; progrès de Stramel.", lacunes:"Chute de 21 rangs : pool vidé par les graduations et les échanges."}}, |
|
102 |
+ MTL:{nom:"Canadiens de Montréal", c1:"#AF1E2D", c2:"#192168", pool:9, banque:{forces:"Espoir de calibre A- à chaque position (Fowler, Hage, Zharovsky, Reinbacher).", lacunes:"Manque d'espoir élite pur depuis la graduation de Demidov."}}, |
|
103 |
+ NSH:{nom:"Predators de Nashville", c1:"#FFB81C", c2:"#041E42", pool:5, banque:{forces:"Peut-être le pool le plus profond (16 espoirs des 2 premières rondes).", lacunes:"Il manque un espoir A-plus (vedette)."}}, |
|
104 |
+ NJD:{nom:"Devils du New Jersey", c1:"#CE1126", c2:"#000000", pool:22, banque:{forces:"Gardien étoile (Yegorov), Silayev et de vrais espoirs D.", lacunes:"Aucun top espoir à l'attaque."}}, |
|
105 |
+ NYI:{nom:"Islanders de New York", c1:"#00539B", c2:"#F47D30", pool:12, banque:{forces:"Pool transformé : Ritchie + classe 2025 (Aitcheson, Eklund, Eiserman).", lacunes:"Gardiens minces derrière Gamzin après la graduation de Schaefer."}}, |
|
106 |
+ NYR:{nom:"Rangers de New York", c1:"#0038A8", c2:"#CE1126", pool:18, banque:{forces:"Perreault (espoir premium) + Šmits (5e au total, 2026).", lacunes:"Manque de centres offensifs de haut niveau."}}, |
|
107 |
+ OTT:{nom:"Sénateurs d'Ottawa", c1:"#DA1A32", c2:"#B79257", pool:26, banque:{forces:"Deux vrais espoirs D droitiers (Yakemchuk, Hensler); gardiens en quantité.", lacunes:"Peu de potentiel offensif de premier plan dans le reste du pool."}}, |
|
108 |
+ PHI:{nom:"Flyers de Philadelphie", c1:"#F74902", c2:"#000000", pool:8, banque:{forces:"Vedette à l'aile (Martone), bons espoirs C et D, bonne profondeur.", lacunes:"Pas d'espoir vedette au centre ni à la ligne bleue."}}, |
|
109 |
+ PIT:{nom:"Penguins de Pittsburgh", c1:"#FCB514", c2:"#000000", pool:16, banque:{forces:"Groupe transformé en 2 saisons (Horcoff, Brunicke, McGroarty, Zonnon).", lacunes:"Manque un espoir premium capable de changer le plafond de l'organisation."}}, |
|
110 |
+ SJS:{nom:"Sharks de San Jose", c1:"#006D75", c2:"#EA7200", pool:2, banque:{forces:"Top espoirs partout : Misa, Dickinson, Ravensbergen + Stenberg (2e, 2026); défenseurs mobiles en quantité.", lacunes:"Profondeur au centre derrière Misa moins garnie; ailiers marqueurs recherchés."}}, |
|
111 |
+ SEA:{nom:"Kraken de Seattle", c1:"#001628", c2:"#99D9D9", pool:7, banque:{forces:"Pool le plus nombreux; deux top espoirs au centre (Catton, O'Brien) + Reid (7e, 2026) en défense.", lacunes:"Longtemps sans top espoir en défense (en partie comblé par Reid)."}}, |
|
112 |
+ STL:{nom:"Blues de St. Louis", c1:"#002F87", c2:"#FCB514", pool:10, banque:{forces:"Espoirs de haut niveau à chaque position (Carbonneau, Dvorsky, Jiricek) + Dagenais (16e, 2026).", lacunes:"Pas d'espoir véritablement élite."}}, |
|
113 |
+ TBL:{nom:"Lightning de Tampa Bay", c1:"#002868", c2:"#FFFFFF", pool:24, banque:{forces:"Geekie et O'Reilly (acquis) + quelques espoirs pertinents.", lacunes:"Pool faible; longue disette de réussite au repêchage."}}, |
|
114 |
+ TOR:{nom:"Maple Leafs de Toronto", c1:"#00205B", c2:"#FFFFFF", pool:29, banque:{forces:"Gavin McKenna (1er au total, 2026) + Cowan — sommet transformé.", lacunes:"Derrière le duo de tête, projections de profondeur seulement (Wheeler, mars 2026)."}}, |
|
115 |
+ UTA:{nom:"Mammoth de l'Utah", c1:"#71AFE5", c2:"#090909", pool:6, banque:{forces:"Qualité : top espoir à chaque position (Iginla, Desnoyers, Simashev, Hrabal) + Belchetz (17e, 2026).", lacunes:"Quantité/profondeur moindre que les autres pools d'élite."}}, |
|
116 |
+ VAN:{nom:"Canucks de Vancouver", c1:"#00205B", c2:"#00843D", pool:15, banque:{forces:"Un espoir de qualité à chaque position (Lekkerimäki, Willander, Cootes) + Malhotra (3e, 2026).", lacunes:"Quantité insuffisante; besoin d'un joueur d'impact au sommet."}}, |
|
117 |
+ VGK:{nom:"Golden Knights de Vegas", c1:"#B4975A", c2:"#333F42", pool:25, banque:{forces:"Connelly (seul 1er choix du pool), gardiens solides.", lacunes:"Défense complètement à sec : aucun défenseur parmi les espoirs classés."}}, |
|
118 |
+ WSH:{nom:"Capitals de Washington", c1:"#C8102E", c2:"#041E42", pool:11, banque:{forces:"5 vrais espoirs ailiers (Cristall, Lakovic, Parascak...) et Hutson en défense.", lacunes:"Aucun espoir légitime au centre; gardiens minces (Suvanto ajouté en 2026)."}}, |
|
119 |
+ WPG:{nom:"Jets de Winnipeg", c1:"#041E42", c2:"#AC162C", pool:20, banque:{forces:"Une demi-douzaine d'espoirs de nom (Yager, Boumedienne...) + Björck (8e, 2026).", lacunes:"Plusieurs 1ers choix peinent à franchir la dernière marche vers la LNH."}}, |
|
120 |
+}; |
|
121 |
+const BANQUE_SOURCE = "Scott Wheeler, The Athletic (classement des banques d'espoirs, mars-avril 2026 — antérieur au repêchage 2026)"; |
|
122 |
+ |
|
123 |
+/* Ordre de base SIMULÉ (classement final 2025-26) : |
|
124 |
+ 1-16 = équipes hors séries (ordre inverse, bris d'égalité officiels du |
|
125 |
+ repêchage 2026), 17-32 = équipes en séries selon l'ordre de la 1re ronde |
|
126 |
+ 2026 (ESPN/NHL.com, juin 2026). */ |
|
127 |
+const ORDRE_HORS_SERIES = ["VAN","CHI","NYR","CGY","TOR","SEA","WPG","FLA","SJS","NSH","STL","NJD","NYI","CBJ","DET","WSH"]; |
|
128 |
+const ORDRE_SERIES = ["LAK","ANA","UTA","EDM","PHI","PIT","BOS","MIN","TBL","DAL","BUF","MTL","COL","VGK","CAR","OTT"]; |
|
129 |
+ |
|
130 |
+/* Table NOMINALE officielle de la loterie 2026 (NHL.com / Sportsnet, |
|
131 |
+ combinaisons sur 1000 : 185/135/…/5). Règle des 10 rangs : au 1er tirage, |
|
132 |
+ seuls les rangs 1-11 sont admissibles et les 7,0 points des rangs 12-16 |
|
133 |
+ sont transférés à la pire équipe (effectif rang 1 : 25,5 % — Sportsnet) ; |
|
134 |
+ au 2e tirage, les rangs 1-12 sont admissibles. */ |
|
135 |
+const COTES_NOMINALES = [18.5, 13.5, 11.5, 9.5, 8.5, 7.5, 6.5, 6.0, 5.0, 3.5, 3.0, 2.5, 2.0, 1.5, 0.5, 0.5]; |
|
136 |
+const LOTERIE_SOURCE = "Table nominale officielle de la loterie 2026 — NHL.com « 2026 Draft Lottery Guide » / Sportsnet, avril-mai 2026"; |
|
137 |
+ |
|
138 |
+/* Choix de 1re ronde 2027 échangés (Phase D — Wikipedia « 2027 NHL entry |
|
139 |
+ draft », PuckPedia, NHL.com, ESPN, consultés le 2026-08-08). Les conditions |
|
140 |
+ sont réévaluées dynamiquement selon le rang (loterie comprise). */ |
|
141 |
+const PICKS_ECHANGES = { |
|
142 |
+ FLA:{resoudre:(r)=>({detenteur:"CHI"}), condition:"Sans protection (condition convertie le 2026-04-16).", transaction:"Éch. Seth Jones ↔ Spencer Knight + ce choix (2025-03-01).", source:"Wikipedia / PuckPedia"}, |
|
143 |
+ TOR:{resoudre:(r)=>({detenteur:"PHI", note:"Protection LEVÉE : en gagnant la loterie 2026 (McKenna), TOR a résolu la chaîne de conditions — le 1er tour 2027 va à PHI sans aucune protection (BOS reçoit le 1er tour 2028 non protégé). Rapporté par PuckPedia/Heavy, confirmation formelle de la LNH en attente."}), |
|
144 |
+ condition:"SANS PROTECTION depuis la loterie 2026 : la victoire de TOR (McKenna 1er au total) a basculé la condition — même un choix top-10 en 2027 part à PHI.", transaction:"Éch. Scott Laughton (PHI, 2025-03-06) / Brandon Carlo (BOS, 2025-03-07) ; bascule résolue en mai 2026.", source:"PuckPedia / Heavy Sports (mai 2026) / Wikipedia"}, |
|
145 |
+ TBL:{resoudre:(r)=> r<=10 ? {detenteur:"TBL", note:"Protection top-10 déclenchée : le choix reste à TBL (SEA recevra le 1er tour 2028 + un 3e tour 2028)."} : {detenteur:"SEA"}, |
|
146 |
+ condition:"Protégé top-10 : si top-10, devient le 1er tour 2028 de TBL (+ 3e tour 2028 pour SEA).", transaction:"Éch. Yanni Gourde / Oliver Bjorkstrand (2025-03-05).", source:"NHL.com (Kraken) / ESPN / Wikipedia"}, |
|
147 |
+ COL:{resoudre:(r)=> r<=10 ? {detenteur:"COL", note:"Protection top-10 déclenchée : TOR recevra plutôt le 1er tour 2028 de COL non protégé."} : {detenteur:"TOR"}, |
|
148 |
+ condition:"Protégé top-10 : si top-10, TOR reçoit le 1er tour 2028 de COL non protégé.", transaction:"Éch. Nicolas Roy (2026-03-05).", source:"ESPN / Wikipedia"}, |
|
149 |
+ EDM:{resoudre:(r)=> r<=12 ? {detenteur:"EDM", note:"Top-12 : EDM peut choisir de transférer plutôt son 1er tour 2028 à CHI — issue incertaine, choix affiché à EDM."} : {detenteur:"CHI"}, |
|
150 |
+ condition:"Si top-12, EDM peut différer et transmettre son 1er tour 2028 à CHI.", transaction:"Éch. Andrew Mangiapane ↔ Dickinson + Dach (2026-03-04).", source:"PuckPedia / Wikipedia"}, |
|
151 |
+ VGK:{resoudre:(r)=> r<=10 ? {detenteur:"VGK", note:"Protection top-10 déclenchée : NJD recevra plutôt un 1er tour 2028."} : {detenteur:"NJD"}, |
|
152 |
+ condition:"Protégé top-10 (via CGY) : si top-10, NJD reçoit un 1er tour 2028.", transaction:"VGK→CGY (2026-01-18), puis CGY→NJD dans l'éch. Simon Nemec (2026-06-23).", source:"Wikipedia / PuckPedia / Pro Hockey Rumors"}, |
|
153 |
+}; |
|
154 |
+ |
|
155 |
+const DRAPEAUX = {CAN:"🇨🇦", USA:"🇺🇸", RUS:"🇷🇺", SWE:"🇸🇪", FIN:"🇫🇮", CZE:"🇨🇿", SVK:"🇸🇰", SUI:"🇨🇭", GER:"🇩🇪", LVA:"🇱🇻", "n.d.":"🏳️"}; |
|
156 |
+const COULEURS_LIGUE = {WHL:"#F59E0B", OHL:"#EF4444", "LHJMQ":"#4FC3F7", NCAA:"#22C55E", "NTDP/USHL":"#818CF8", USHL:"#818CF8", "MHL (Russie)":"#F87171", "J20 Nationell":"#FBBF24", "U18 Nationell":"#FBBF24", "U20 SM-sarja":"#60A5FA", "Extraliga (Tchéquie)":"#F472B6", "Tchéquie U20":"#F472B6", "NL (Suisse)":"#A78BFA", "DEL (Allemagne)":"#34D399", "USHS-Prep":"#9CA3AF", NAHL:"#9CA3AF"}; |
|
157 |
+ |
|
158 |
+/* ============================================================ |
|
159 |
+ ESPOIRS — stats 2025-26 (dernière saison complète), rangs par |
|
160 |
+ source datés, analyses/forces/faiblesses = synthèses originales. |
|
161 |
+ radar = évaluation ÉDITORIALE 20-80 synthétisée des rapports |
|
162 |
+ publics (pas des notes officielles). null = introuvable (n.d.). |
|
163 |
+ ============================================================ */ |
|
164 |
+const ESPOIRS = [ |
|
165 |
+ {id:"dupont", nom:"Landon DuPont", position:"D", tir:"D", taille:"6'00\"", tailleCm:183, poids:190, naissance:"2009-05-28", nationalite:"CAN", |
|
166 |
+ equipeActuelle:"Université du Michigan (ex-Everett)", ligue:"NCAA", |
|
167 |
+ stats:{mj:63,b:18,p:55,pts:73,plusMoins:59,moy:null,arr:null}, statsLigue:"WHL", |
|
168 |
+ rangsParSource:{wheeler:1,dfo:1,tank:1,thn:1,br:1,button:3}, tendance:"up", risque:"faible", sleeper:false, |
|
169 |
+ forces:["Transport de rondelle et patinage de calibre exceptionnel pour son âge","Vision et relances de premier plan (55 passes en 63 matchs)","Production historique : +59, champion WHL et Coupe Memorial 2026","Leadership précoce — capitaine du Canada au Hlinka-Gretzky 2026 (or)"], |
|
170 |
+ faiblesses:["Gabarit moyen (6'0\") pour un défenseur de premier duo","Défense en zone propre encore à raffiner contre des adultes (NCAA en 2026-27)"], |
|
171 |
+ comparableLNH:"Profil de défenseur droitier offensif moderne, à la Evan Bouchard (style, pas une promesse)", |
|
172 |
+ projectionPlafond:"Défenseur no 1", radar:{patinage:70,sensJeu:70,tir:55,competitivite:60,jeuDefensif:55}, |
|
173 |
+ analyse:"Premier défenseur de l'histoire de la WHL admis sous le statut exceptionnel (2e joueur après Bedard), fils de Micki DuPont. No 1 quasi unanime (6 sources sur 7 ; seul l'aperçu TSN de nov. 2025 le plaçait 3e). Il rejoint l'Université du Michigan en 2026-27 — sa saison NCAA à 17 ans sera le vrai test. Poids rapporté entre 177 et 190 lb selon les sources."}, |
|
174 |
+ {id:"joseph", nom:"Alexis Joseph", position:"C", tir:"G", taille:"6'04\"", tailleCm:196, poids:207, naissance:"2009-06-16", nationalite:"CAN", |
|
175 |
+ equipeActuelle:"Sea Dogs de Saint John", ligue:"LHJMQ", |
|
176 |
+ stats:{mj:54,b:24,p:36,pts:60,plusMoins:null,moy:null,arr:null}, statsLigue:"LHJMQ", |
|
177 |
+ rangsParSource:{wheeler:2,dfo:3,tank:3,thn:2,br:2,button:1}, tendance:"stable", risque:"faible", sleeper:false, |
|
178 |
+ forces:["Centre de 6'4\"-6'5\" avec des mains de marqueur","Point par match comme recrue de 16 ans dans la LHJMQ","Jeu complet : 50,1 % aux mises en jeu dès sa 1re saison","Assistant-capitaine du Canada au Hlinka-Gretzky 2026 (or)"], |
|
179 |
+ faiblesses:["Coup de patin à alourdir pour suivre le rythme LNH","Doit dicter le jeu plus constamment soir après soir"], |
|
180 |
+ comparableLNH:"Grand centre à deux vitesses, profil à la Tage Thompson (style, pas une promesse)", |
|
181 |
+ projectionPlafond:"Centre de premier trio", radar:{patinage:55,sensJeu:65,tir:60,competitivite:65,jeuDefensif:55}, |
|
182 |
+ analyse:"Premier choix du repêchage LHJMQ 2025. Wheeler le décrit comme « le meilleur espoir de la LHJMQ depuis Alexis Lafrenière » et Craig Button le plaçait 1er en novembre 2025. Bémol frais : un Hlinka-Gretzky discret (1B-2P en 4 matchs, 43e pointeur du tournoi malgré le rôle d'assistant-capitaine du club champion) qui lui coûte un rang dans le consensus ajusté — sa saison LHJMQ 2026-27 dira si c'était un accident de parcours."}, |
|
183 |
+ {id:"privalov", nom:"Nazar Privalov", position:"AG", tir:"G", taille:"6'04\"", tailleCm:193, poids:214, naissance:"2009-05-25", nationalite:"RUS", |
|
184 |
+ equipeActuelle:"Krasnaya Armiya Moskva (CSKA jr)", ligue:"MHL (Russie)", |
|
185 |
+ stats:{mj:51,b:30,p:19,pts:49,plusMoins:null,moy:null,arr:null}, statsLigue:"MHL", |
|
186 |
+ rangsParSource:{wheeler:3,dfo:2,tank:2,thn:4,br:3,button:9}, tendance:"down", risque:"élevé", sleeper:false, |
|
187 |
+ forces:["Ailier de puissance de 6'4\" et plus de 210 lb","30 buts à 16 ans dans la MHL — seul Michkov a fait mieux au même âge","Tir et jeu autour du filet dominants pour sa cohorte"], |
|
188 |
+ faiblesses:["Contrat de 4 ans signé avec le CSKA (KHL) jusqu'en juin 2030 — disponibilité incertaine","Absent des tournois IIHF (Russie toujours exclue) : peu de matchs repères contre l'élite mondiale"], |
|
189 |
+ comparableLNH:"Ailier de puissance marqueur, profil à la Valeri Nichushkin (style, pas une promesse)", |
|
190 |
+ projectionPlafond:"Ailier top-6 d'impact", radar:{patinage:55,sensJeu:60,tir:70,competitivite:60,jeuDefensif:45}, |
|
191 |
+ analyse:"Talent brut de top-3 (2e chez Daily Faceoff et Tankathon), mais son contrat KHL jusqu'en 2030 est le grand point d'interrogation de la cuvée : plusieurs sources anticipent une glissade le soir du repêchage. Recrue de l'année MHL 2025-26."}, |
|
192 |
+ {id:"skvortsov", nom:"Sergei Skvortsov", position:"AG", tir:"D", taille:"6'00\"", tailleCm:183, poids:160, naissance:"2009-03-11", nationalite:"RUS", |
|
193 |
+ equipeActuelle:"Chaika Nizhny Novgorod", ligue:"MHL (Russie)", |
|
194 |
+ stats:{mj:52,b:19,p:24,pts:43,plusMoins:null,moy:null,arr:null}, statsLigue:"MHL", |
|
195 |
+ rangsParSource:{wheeler:5,dfo:4,tank:6,br:5}, tendance:"stable", risque:"moyen", sleeper:false, |
|
196 |
+ forces:["Meilleur pointeur de son club à 16 ans","Match de 4 buts en séries MHL","Sens offensif et toucher de passe au-dessus de sa cohorte"], |
|
197 |
+ faiblesses:["Très frêle (154-165 lb selon les sources) — développement physique à suivre","Comme tous les espoirs russes : moins de matchs repères internationaux"], |
|
198 |
+ comparableLNH:"Ailier créatif longiligne, profil à la Kirill Marchenko (style, pas une promesse)", |
|
199 |
+ projectionPlafond:"Ailier top-6", radar:{patinage:60,sensJeu:65,tir:60,competitivite:50,jeuDefensif:40}, |
|
200 |
+ analyse:"Classé entre 4e et 6e par toutes les sources qui l'ont évalué — l'un des consensus les plus stables du top-10. Son gabarit à remplir est le principal frein à une projection plus haute."}, |
|
201 |
+ {id:"meyer", nom:"Carter Meyer", position:"C", tir:"G", taille:"6'00\"", tailleCm:183, poids:176, naissance:"2009-04-10", nationalite:"USA", |
|
202 |
+ equipeActuelle:"Remparts de Québec (dès 2026-27, ex-NTDP)", ligue:"LHJMQ", |
|
203 |
+ stats:{mj:41,b:18,p:27,pts:45,plusMoins:-20,moy:null,arr:null}, statsLigue:"NTDP U17", |
|
204 |
+ rangsParSource:{wheeler:6,dfo:5,tank:4,thn:5,br:6,button:2}, tendance:"down", risque:"moyen", sleeper:false, |
|
205 |
+ forces:["Plus d'un point par match avec le NTDP U17 (45 pts en 41 MJ)","10 points en 4 matchs au Défi mondial U17 (bronze)","Fils de l'ex-défenseur LNH Freddy Meyer — pedigree et sens du jeu"], |
|
206 |
+ faiblesses:["Libéré du programme national américain le 2026-07-14 — trajectoire chamboulée","-20 avec le U17; jeu sans la rondelle à solidifier"], |
|
207 |
+ comparableLNH:"Centre offensif polyvalent, profil à la Cole Caufield déplacé au centre (style, pas une promesse)", |
|
208 |
+ projectionPlafond:"Centre top-6", radar:{patinage:60,sensJeu:60,tir:55,competitivite:60,jeuDefensif:50}, |
|
209 |
+ analyse:"Craig Button le voyait 2e en novembre 2025. Sa libération surprise du NTDP (rapportée par Jeff Marek) l'amène aux Remparts de Québec pour 2026-27, avant Boston University en 2028-29 : une saison LHJMQ dominante pourrait le relancer vers le top-5."}, |
|
210 |
+ {id:"sundstrom", nom:"Milan Sundström", position:"C", tir:"G", taille:"6'02\"", tailleCm:188, poids:187, naissance:"2009-05-06", nationalite:"SWE", |
|
211 |
+ equipeActuelle:"MoDo Hockey U20", ligue:"J20 Nationell", |
|
212 |
+ stats:{mj:12,b:12,p:8,pts:20,plusMoins:null,moy:null,arr:null}, statsLigue:"J20", |
|
213 |
+ rangsParSource:{wheeler:4,dfo:15,tank:5,thn:3,br:4,button:7}, tendance:"up", risque:"moyen", sleeper:false, |
|
214 |
+ forces:["12 buts en 12 matchs J20 à 16 ans (plus 32 pts en 16 MJ au U18)","Meilleur joueur de la Suède au Hlinka-Gretzky 2026 (Daily Faceoff), but en prolongation contre la Slovaquie","Centre complet avec pedigree (fils de Niklas Sundström)"], |
|
215 |
+ faiblesses:["Classé entre 3e et 15e selon les sources — fourchette large","Échantillon J20 encore mince (12 matchs)"], |
|
216 |
+ comparableLNH:"Centre bidirectionnel suédois, profil à la William Karlsson offensif (style, pas une promesse)", |
|
217 |
+ projectionPlafond:"Centre top-6", radar:{patinage:55,sensJeu:65,tir:55,competitivite:60,jeuDefensif:60}, |
|
218 |
+ analyse:"Le meilleur Suédois de la cuvée. Presque toutes les sources le voient 3e-5e; Daily Faceoff (15e) est l'exception — d'où sa fourchette affichée. Son Hlinka solide dans une équipe suédoise faible (7e) a confirmé son statut."}, |
|
219 |
+ {id:"nelson", nom:"Sammy Nelson", position:"C", tir:"D", taille:"6'02\"", tailleCm:189, poids:192, naissance:"2008-09-19", nationalite:"USA", |
|
220 |
+ equipeActuelle:"Université Notre Dame (ex-NTDP U18)", ligue:"NCAA", |
|
221 |
+ stats:{mj:58,b:27,p:27,pts:54,plusMoins:null,moy:null,arr:null}, statsLigue:"NTDP U18", |
|
222 |
+ rangsParSource:{wheeler:8,dfo:6,tank:7,br:9}, tendance:"up", risque:"faible", sleeper:false, |
|
223 |
+ forces:["2e pointeur du NTDP U18 avec 5 buts gagnants","10 points en 18 matchs contre des équipes NCAA","Cote « A » sur la liste préliminaire de la Centrale de recrutement","Parmi les plus vieux de la cuvée (raté 2026 de 4 jours) : plus mature, saut direct en NCAA"], |
|
224 |
+ faiblesses:["Son âge gonfle la comparaison avec les plus jeunes de la cuvée","Doit prouver qu'il peut piloter un trio en NCAA dès 2026-27"], |
|
225 |
+ comparableLNH:"Centre nord-sud robuste, profil à la Brayden Schenn (style, pas une promesse)", |
|
226 |
+ projectionPlafond:"Centre top-6", radar:{patinage:55,sensJeu:60,tir:60,competitivite:60,jeuDefensif:55}, |
|
227 |
+ analyse:"Frère de Danny Nelson (Islanders). Candidat au Mondial junior 2027 selon NHL.com. Son passage direct à Notre Dame en fait l'un des espoirs les plus faciles à évaluer cette saison."}, |
|
228 |
+ {id:"england", nom:"Brock England", position:"C", tir:"G", taille:"5'11\"", tailleCm:180, poids:174, naissance:"2009-08-22", nationalite:"CAN", |
|
229 |
+ equipeActuelle:"Thunderbirds de Seattle", ligue:"WHL", |
|
230 |
+ stats:{mj:64,b:21,p:30,pts:51,plusMoins:null,moy:null,arr:null}, statsLigue:"WHL", |
|
231 |
+ rangsParSource:{wheeler:7,dfo:7,tank:9,br:7,button:5}, tendance:"up", risque:"faible", sleeper:false, |
|
232 |
+ forces:["« Le meilleur patineur que j'ai vu dans cette cuvée » — Scott Wheeler","2 buts dans la finale du Hlinka-Gretzky 2026 (Canada 8-1 USA)","Moteur et rythme constants, dangereux en transition"], |
|
233 |
+ faiblesses:["Parmi les plus jeunes de la cuvée (né en août 2009) — encore léger (174 lb)","Doit convertir davantage son volume de chances en buts"], |
|
234 |
+ comparableLNH:"Centre explosif, profil à la Dylan Larkin (style, pas une promesse)", |
|
235 |
+ projectionPlafond:"Centre top-6", radar:{patinage:70,sensJeu:60,tir:50,competitivite:60,jeuDefensif:50}, |
|
236 |
+ analyse:"Sa finale de Hlinka (2 buts le 8 août 2026) est le fait d'armes le plus récent de toute la cuvée. Le patin d'élite est la fondation ; la production WHL devrait exploser en 2026-27 avec un rôle élargi à Seattle."}, |
|
237 |
+ {id:"zhilkin", nom:"Dima Zhilkin", position:"AD", tir:"D", taille:"5'10\"", tailleCm:178, poids:185, naissance:"2008-10-21", nationalite:"CAN", |
|
238 |
+ equipeActuelle:"Spirit de Saginaw (capitaine)", ligue:"OHL", |
|
239 |
+ stats:{mj:59,b:36,p:39,pts:75,plusMoins:null,moy:null,arr:null}, statsLigue:"OHL", |
|
240 |
+ rangsParSource:{wheeler:9,dfo:9,tank:8,br:8}, tendance:"up", risque:"faible", sleeper:false, |
|
241 |
+ forces:["36 buts et 100 minutes de punition : marqueur ET abrasif","5 buts en 5 matchs au Mondial U18 2026 comme sous-classé","Nommé capitaine de Saginaw avant ses 17 ans"], |
|
242 |
+ faiblesses:["Taille moyenne (5'10\") pour son style physique","Emballement/discipline à canaliser (100 PIM)"], |
|
243 |
+ comparableLNH:"Ailier marqueur teigneux, profil à la Brady Tkachuk format compact (style, pas une promesse)", |
|
244 |
+ projectionPlafond:"Ailier top-6", radar:{patinage:60,sensJeu:55,tir:65,competitivite:65,jeuDefensif:45}, |
|
245 |
+ analyse:"Frère de Danil Zhilkin (Jets). The Hockey News le cite déjà comme cible potentielle de loterie. Son U18 dominant en avril 2026 (6e marqueur du tournoi comme sous-classé) est l'un des meilleurs arguments statistiques de la cuvée."}, |
|
246 |
+ {id:"jacobson", nom:"Jaxon Jacobson", position:"C", tir:"G", taille:"5'10\"", tailleCm:176, poids:176, naissance:"2008-12-11", nationalite:"CAN", |
|
247 |
+ equipeActuelle:"Wheat Kings de Brandon", ligue:"WHL", |
|
248 |
+ stats:{mj:63,b:25,p:60,pts:85,plusMoins:8,moy:null,arr:null}, statsLigue:"WHL", |
|
249 |
+ rangsParSource:{wheeler:10,dfo:10,tank:10,thn:10,br:10}, tendance:"up", risque:"moyen", sleeper:false, |
|
250 |
+ forces:["85 points en 63 matchs — la meilleure production CHL de la cuvée","Vision de passeur d'élite (60 passes)","A produit malgré une blessure en cours de saison"], |
|
251 |
+ faiblesses:["5'9\"-5'10\" selon les sources : le gabarit divisera les recruteurs","Jeu défensif encore embryonnaire"], |
|
252 |
+ comparableLNH:"Petit centre créatif, profil à la Logan Stankoven (style, pas une promesse)", |
|
253 |
+ projectionPlafond:"Centre/ailier top-6", radar:{patinage:55,sensJeu:70,tir:50,competitivite:55,jeuDefensif:45}, |
|
254 |
+ analyse:"Rang 10 unanime chez les cinq sources qui le classent — fait rarissime. L'écart entre sa production (no 1 de la cuvée en CHL) et son rang consensus en fait aussi un candidat « valeur » : seul le gabarit explique la retenue."}, |
|
255 |
+ {id:"neuenschwander", nom:"Jonah Neuenschwander", position:"C", tir:"G", taille:"6'03\"", tailleCm:190, poids:187, naissance:"2009-03-10", nationalite:"SUI", |
|
256 |
+ equipeActuelle:"EHC Bienne", ligue:"NL (Suisse)", |
|
257 |
+ stats:{mj:32,b:5,p:7,pts:12,plusMoins:null,moy:null,arr:null}, statsLigue:"National League (pro)", |
|
258 |
+ rangsParSource:{wheeler:11,dfo:14,tank:11,thn:7,button:8}, tendance:"stable", risque:"moyen", sleeper:false, |
|
259 |
+ forces:["Joueur D-1 le plus productif de l'élite suisse en 60 ans","Déjà deux Mondiaux juniors disputés (le premier à 15 ans, une première depuis 2001)","Grand centre (6'3\") habitué au hockey d'hommes"], |
|
260 |
+ faiblesses:["Production brute modeste en pro (12 pts) — rôle limité","Position finale à trancher (centre ou aile selon les sources)"], |
|
261 |
+ comparableLNH:"Grand centre européen deux sens, profil à la Nico Hischier (style, pas une promesse)", |
|
262 |
+ projectionPlafond:"Centre top-9 avec plafond top-6", radar:{patinage:55,sensJeu:55,tir:55,competitivite:60,jeuDefensif:55}, |
|
263 |
+ analyse:"Le meilleur espoir suisse depuis Hischier selon plusieurs observateurs. Évaluation difficile : ses 12 points en National League valent plus qu'ils n'y paraissent (25 pts en 18 MJ au niveau U21)."}, |
|
264 |
+ {id:"yakunin", nom:"Yevgeni Yakunin", position:"C", tir:"G", taille:"6'03\"", tailleCm:190, poids:194, naissance:"2009-02-09", nationalite:"RUS", |
|
265 |
+ equipeActuelle:"MHK Spartak Moskva", ligue:"MHL (Russie)", |
|
266 |
+ stats:{mj:58,b:13,p:34,pts:47,plusMoins:null,moy:null,arr:null}, statsLigue:"MHL", |
|
267 |
+ rangsParSource:{wheeler:13,dfo:17,tank:12}, tendance:"stable", risque:"élevé", sleeper:false, |
|
268 |
+ forces:["Record MHL d'assistances pour un joueur U17 (34)","Grand centre passeur de 6'3\"","Production régulière sur 58 matchs"], |
|
269 |
+ faiblesses:["Contrat KHL avec le Spartak Moscou jusqu'en 2031 — l'engagement le plus long de la cuvée, pire que Privalov","Tir peu menaçant (13 buts)"], |
|
270 |
+ comparableLNH:"Centre passeur format pro, profil à la Anton Lundell (style, pas une promesse)", |
|
271 |
+ projectionPlafond:"Centre top-9", radar:{patinage:50,sensJeu:65,tir:50,competitivite:55,jeuDefensif:55}, |
|
272 |
+ analyse:"Le contrat jusqu'en 2031 (Daily Faceoff) pèsera sur son rang réel. Le talent de fabricant de jeu, lui, est indéniable — record historique U17 de la MHL à l'appui."}, |
|
273 |
+ {id:"cripps", nom:"Brock Cripps", position:"D", tir:"D", taille:"5'10\"", tailleCm:178, poids:161, naissance:"2009-07-23", nationalite:"CAN", |
|
274 |
+ equipeActuelle:"Raiders de Prince Albert", ligue:"WHL", |
|
275 |
+ stats:{mj:62,b:6,p:31,pts:37,plusMoins:null,moy:null,arr:null}, statsLigue:"WHL", |
|
276 |
+ rangsParSource:{wheeler:15,dfo:16,tank:17,thn:9}, tendance:"up", risque:"moyen", sleeper:false, |
|
277 |
+ forces:["2e choix du repêchage WHL 2024 ; ~26 minutes par match au Mondial U17 (or)","21 points en 20 matchs de séries WHL — a élevé son jeu","Défenseur droitier mobile et intelligent, denrée rare"], |
|
278 |
+ faiblesses:["161 lb : très loin d'un gabarit LNH","Devra prouver qu'il peut défendre contre du volume physique"], |
|
279 |
+ comparableLNH:"D droitier mobile sous-format, profil à la Jared Spurgeon (style, pas une promesse)", |
|
280 |
+ projectionPlafond:"Défenseur top-4", radar:{patinage:60,sensJeu:65,tir:45,competitivite:55,jeuDefensif:55}, |
|
281 |
+ analyse:"The Hockey News le place déjà 9e. Ses séries WHL (plus d'un point par match) et son or au Défi mondial U17 avec un temps de glace massif dessinent un défenseur no 2-3 de confiance."}, |
|
282 |
+ {id:"pustovoy", nom:"Andrei Pustovoy", position:"AD", tir:"G", taille:"6'02\"", tailleCm:190, poids:198, naissance:"2008-12-08", nationalite:"RUS", |
|
283 |
+ equipeActuelle:"Loko Yaroslavl", ligue:"MHL (Russie)", |
|
284 |
+ stats:{mj:52,b:32,p:30,pts:62,plusMoins:null,moy:null,arr:null}, statsLigue:"MHL", |
|
285 |
+ rangsParSource:{wheeler:14,dfo:18,tank:13}, tendance:"stable", risque:"moyen", sleeper:false, |
|
286 |
+ forces:["Joueur U18 le plus productif de la MHL en 2025-26 (62 pts)","32 buts : gâchette naturelle avec gabarit (6'2\"-6'3\", ~200 lb)","Profil puissance-finition déjà mûr physiquement"], |
|
287 |
+ faiblesses:["Patinage à raffiner pour le rythme nord-américain","Jeu de soutien défensif inconstant"], |
|
288 |
+ comparableLNH:"Ailier marqueur de puissance, profil à la Andrei Svechnikov (style, pas une promesse)", |
|
289 |
+ projectionPlafond:"Ailier top-6", radar:{patinage:55,sensJeu:55,tir:65,competitivite:55,jeuDefensif:45}, |
|
290 |
+ analyse:"Statistiquement, le meilleur attaquant U18 de toute la MHL. Classé 13e-18e par les trois sources qui le suivent — la stabilité du consensus tranche avec le peu de visibilité médiatique des Russes."}, |
|
291 |
+ {id:"kazda", nom:"Timothy Kazda", position:"AD", tir:"D", taille:"6'01\"", tailleCm:185, poids:194, naissance:"2008-10-04", nationalite:"SVK", |
|
292 |
+ equipeActuelle:"Steel de Chicago", ligue:"USHL", |
|
293 |
+ stats:{mj:59,b:22,p:19,pts:41,plusMoins:-5,moy:null,arr:null}, statsLigue:"USHL", |
|
294 |
+ rangsParSource:{wheeler:null,dfo:11,tank:21}, mentionWheeler:true, tendance:"stable", risque:"moyen", sleeper:false, |
|
295 |
+ forces:["Première équipe des recrues USHL 2026","12 points en 12 matchs internationaux U18 avec la Slovaquie","Ailier énergique qui gagne ses batailles de rondelle"], |
|
296 |
+ faiblesses:["Fourchette large : 11e (Daily Faceoff) contre mention honorable (Wheeler)","Création de jeu à cinq contre cinq à démontrer"], |
|
297 |
+ comparableLNH:"Ailier de puissance slovaque, profil à la Martin Pospisil offensif (style, pas une promesse)", |
|
298 |
+ projectionPlafond:"Ailier top-9", radar:{patinage:55,sensJeu:50,tir:60,competitivite:65,jeuDefensif:50}, |
|
299 |
+ analyse:"Le meilleur Slovaque de la cuvée. Daily Faceoff (11e) est nettement plus haut que Wheeler (mention honorable) — affiché en fourchette, conformément aux règles de la plateforme."}, |
|
300 |
+ {id:"santala", nom:"Luca Santala", position:"C", tir:"D", taille:"6'02\"", tailleCm:188, poids:176, naissance:"2009-07-28", nationalite:"FIN", |
|
301 |
+ equipeActuelle:"Knights de London (dès 2026-27, ex-Kiekko-Espoo)", ligue:"OHL", |
|
302 |
+ stats:{mj:42,b:19,p:15,pts:34,plusMoins:null,moy:null,arr:null}, statsLigue:"U18+U20 Finlande (combiné)", |
|
303 |
+ rangsParSource:{wheeler:21,dfo:12,tank:18,thn:8,button:6}, tendance:"up", risque:"moyen", sleeper:false, |
|
304 |
+ forces:["Meilleur espoir finlandais 2009","Grand centre polyvalent qui joue dans les deux sens","Transfert chez les Knights de London (OHL) — machine à développement"], |
|
305 |
+ faiblesses:["Classé entre 6e et 21e : les sources sont divisées","Production U20 modeste (12 pts en 25 MJ) avant sa montée"], |
|
306 |
+ comparableLNH:"Centre finlandais complet, profil à la Anton Lundell (style, pas une promesse)", |
|
307 |
+ projectionPlafond:"Centre top-9 avec plafond top-6", radar:{patinage:55,sensJeu:60,tir:55,competitivite:55,jeuDefensif:55}, |
|
308 |
+ analyse:"Son passage à London (signé le 23 juillet 2026, CHL.ca) est le meilleur indicateur de confiance : les Knights ne recrutent pas des projets ordinaires en Europe. La fourchette 6e-21e reflète l'incertitude du saut nord-américain."}, |
|
309 |
+ {id:"tomek", nom:"Petr Tomek", position:"C", tir:"G", taille:"5'10\"", tailleCm:178, poids:161, naissance:"2008-10-23", nationalite:"CZE", |
|
310 |
+ equipeActuelle:"HC Energie Karlovy Vary", ligue:"Extraliga (Tchéquie)", |
|
311 |
+ stats:{mj:51,b:13,p:7,pts:20,plusMoins:null,moy:null,arr:null}, statsLigue:"Extraliga (pro)", |
|
312 |
+ rangsParSource:{wheeler:23,dfo:8,tank:19,button:10}, tendance:"stable", risque:"moyen", sleeper:false, |
|
313 |
+ forces:["13 buts PROS dans l'élite tchèque à 17 ans","Saison complète contre des hommes — rare dans la cuvée","Instincts de marqueur en zone payante"], |
|
314 |
+ faiblesses:["Classé entre 8e et 23e : fourchette très large","Gabarit léger (5'10\", ~161 lb) pour son style direct"], |
|
315 |
+ comparableLNH:"Attaquant tchèque opportuniste, profil à la Ondrej Palat (style, pas une promesse)", |
|
316 |
+ projectionPlafond:"Attaquant top-9", radar:{patinage:60,sensJeu:60,tir:55,competitivite:55,jeuDefensif:45}, |
|
317 |
+ analyse:"Le cas le plus polarisant du milieu de première ronde : Daily Faceoff (8e) valorise ses 13 buts pros, Wheeler (23e) attend de le voir dominer sa cohorte. Né un mois après la date limite 2026 — il aurait été repêché cette année autrement."}, |
|
318 |
+ {id:"fitzhenry", nom:"Nolan Fitzhenry", position:"C", tir:"G", taille:"5'11\"", tailleCm:180, poids:183, naissance:"2009-02-10", nationalite:"USA", |
|
319 |
+ equipeActuelle:"USNTDP (U18 en 2026-27)", ligue:"NTDP/USHL", |
|
320 |
+ stats:{mj:51,b:21,p:24,pts:45,plusMoins:-17,moy:null,arr:null}, statsLigue:"NTDP U17", |
|
321 |
+ rangsParSource:{wheeler:12,dfo:24,tank:14}, tendance:"stable", risque:"moyen", sleeper:false, |
|
322 |
+ forces:["45 points en 51 matchs au NTDP U17","Engagement NCAA vers North Dakota rapporté (Tankathon — non confirmé par une 2e source)","Bon toucher autour du filet (21 buts)"], |
|
323 |
+ faiblesses:["Écart 12e (Wheeler) vs 24e (Daily Faceoff)","-17 dans une équipe U17 en difficulté"], |
|
324 |
+ comparableLNH:"Centre américain travaillant, profil à la Frank Nazar (style, pas une promesse)", |
|
325 |
+ projectionPlafond:"Centre top-9", radar:{patinage:55,sensJeu:60,tir:50,competitivite:55,jeuDefensif:50}, |
|
326 |
+ analyse:"L'un des piliers du NTDP 2009, groupe collectivement affaibli (finale du Hlinka perdue 8-1, départ de Meyer). Sa saison U18 dira s'il suit la trajectoire de Wheeler (12e) ou celle de Daily Faceoff (24e)."}, |
|
327 |
+ {id:"meijer", nom:"Bosse Meijer", position:"C", tir:"G", taille:"5'10\"", tailleCm:178, poids:168, naissance:"2008-12-17", nationalite:"SWE", |
|
328 |
+ equipeActuelle:"Frölunda HC U20", ligue:"J20 Nationell", |
|
329 |
+ stats:{mj:31,b:16,p:21,pts:37,plusMoins:null,moy:null,arr:null}, statsLigue:"J20", |
|
330 |
+ rangsParSource:{wheeler:16,dfo:21,tank:15}, tendance:"up", risque:"moyen", sleeper:false, |
|
331 |
+ forces:["Plus d'un point par match en J20 et ~2 pts/match en séries","8 points en 7 matchs au Mondial U18 2026 comme admissible 2027 (Suède championne)","Débuts déjà faits en SHL"], |
|
332 |
+ faiblesses:["Gabarit moyen (5'10\", 168 lb)","Doit s'imposer physiquement au niveau homme"], |
|
333 |
+ comparableLNH:"Centre suédois fluide, profil à la Leo Carlsson format réduit (style, pas une promesse)", |
|
334 |
+ projectionPlafond:"Centre top-9", radar:{patinage:60,sensJeu:60,tir:50,competitivite:55,jeuDefensif:50}, |
|
335 |
+ analyse:"4e marqueur de la Suède championne du monde U18 en avril 2026 alors qu'il était sous-classé — l'argument international le plus fort du milieu de ronde."}, |
|
336 |
+ {id:"shtyrkhunov", nom:"Vladimir Shtyrkhunov", position:"D", tir:"D", taille:"6'00\"", tailleCm:183, poids:157, naissance:"2009-01-15", nationalite:"RUS", |
|
337 |
+ equipeActuelle:"Krasnaya Armiya Moskva (CSKA jr)", ligue:"MHL (Russie)", |
|
338 |
+ stats:{mj:55,b:4,p:28,pts:32,plusMoins:null,moy:null,arr:null}, statsLigue:"MHL", |
|
339 |
+ rangsParSource:{wheeler:18,dfo:23,tank:20}, tendance:"stable", risque:"élevé", sleeper:false, |
|
340 |
+ forces:["2e saison U17 la plus productive de l'histoire de la MHL pour un défenseur","~20 minutes de jeu par match à 16-17 ans","Relance fluide, D droitier — profil recherché"], |
|
341 |
+ faiblesses:["157 lb : parmi les plus légers de la cuvée","Facteur russe : visibilité et calendrier de venue en Amérique incertains"], |
|
342 |
+ comparableLNH:"D droitier de transition, profil à la Shayne Gostisbehere (style, pas une promesse)", |
|
343 |
+ projectionPlafond:"Défenseur top-4", radar:{patinage:60,sensJeu:60,tir:45,competitivite:50,jeuDefensif:50}, |
|
344 |
+ analyse:"Production historique pour un défenseur U17 de la MHL. Consensus stable (18e-23e) chez les trois sources qui le classent."}, |
|
345 |
+ {id:"davidson", nom:"Noah Davidson", position:"C", tir:"G", taille:"6'03\"", tailleCm:190, poids:216, naissance:"2008-11-01", nationalite:"USA", |
|
346 |
+ equipeActuelle:"Tigers de Medicine Hat", ligue:"WHL", |
|
347 |
+ stats:{mj:67,b:30,p:22,pts:52,plusMoins:null,moy:null,arr:null}, statsLigue:"WHL", |
|
348 |
+ rangsParSource:{wheeler:17,dfo:28,tank:16}, tendance:"stable", risque:"moyen", sleeper:false, |
|
349 |
+ forces:["30 buts comme recrue WHL — rare pour un attaquant de 6'3\", 216 lb","Déjà bâti comme un pro","Engagé avec Boston College (NCAA)"], |
|
350 |
+ faiblesses:["Fourchette 16e-28e selon les sources","Jeu de transition et première passe à polir"], |
|
351 |
+ comparableLNH:"Attaquant de puissance nord-sud, profil à la Chris Kreider (style, pas une promesse)", |
|
352 |
+ projectionPlafond:"Attaquant top-9 avec plafond top-6", radar:{patinage:50,sensJeu:50,tir:60,competitivite:65,jeuDefensif:50}, |
|
353 |
+ analyse:"Le combo 30 buts + 216 lb en saison recrue WHL n'existe nulle part ailleurs dans la cuvée. Nationalité USA confirmée par le tableau officiel du Hlinka-Gretzky d'août 2025, où il a représenté USA U18 (6 pts en 5 matchs)."}, |
|
354 |
+ {id:"gutierrez", nom:"Diego Gutierrez", position:"D", tir:"D", taille:"6'02\"", tailleCm:188, poids:187, naissance:"2009-05-13", nationalite:"USA", |
|
355 |
+ equipeActuelle:"USNTDP (U18 en 2026-27)", ligue:"NTDP/USHL", |
|
356 |
+ stats:{mj:38,b:2,p:17,pts:19,plusMoins:-8,moy:null,arr:null}, statsLigue:"NTDP U17", |
|
357 |
+ rangsParSource:{wheeler:19,dfo:22,tank:25}, tendance:"stable", risque:"moyen", sleeper:false, |
|
358 |
+ forces:["Meilleur défenseur des 2009 du programme américain","Droitier de 6'2\" avec bâton actif","Engagé avec Notre Dame (NCAA)"], |
|
359 |
+ faiblesses:["Production offensive modeste (19 pts en 38 MJ)","Prises de décision sous pression à stabiliser"], |
|
360 |
+ comparableLNH:"D droitier deux sens, profil à la K'Andre Miller côté droit (style, pas une promesse)", |
|
361 |
+ projectionPlafond:"Défenseur top-4", radar:{patinage:55,sensJeu:55,tir:45,competitivite:55,jeuDefensif:60}, |
|
362 |
+ analyse:"Consensus serré (19e-25e). Le NTDP lui confiera les grosses minutes au U18 en 2026-27 — c'est là que son rang bougera."}, |
|
363 |
+ {id:"tait", nom:"Boston Tait", position:"D", tir:"G", taille:"6'02\"", tailleCm:188, poids:183, naissance:"2009-04-13", nationalite:"CAN", |
|
364 |
+ equipeActuelle:"Wild de Wenatchee", ligue:"WHL", |
|
365 |
+ stats:{mj:62,b:5,p:18,pts:23,plusMoins:null,moy:null,arr:null}, statsLigue:"WHL", |
|
366 |
+ rangsParSource:{wheeler:20,dfo:20,tank:31}, tendance:"stable", risque:"moyen", sleeper:false, |
|
367 |
+ forces:["Seul défenseur gaucher du top-25 de Wheeler","~21 minutes par match à 16-17 ans","Gabarit et rayon d'action de défenseur moderne"], |
|
368 |
+ faiblesses:["Production offensive limitée (23 pts)","55 PIM : discipline à surveiller"], |
|
369 |
+ comparableLNH:"D gaucher fiable, profil à la Jake Sanderson défensif (style, pas une promesse)", |
|
370 |
+ projectionPlafond:"Défenseur top-4", radar:{patinage:55,sensJeu:50,tir:45,competitivite:55,jeuDefensif:60}, |
|
371 |
+ analyse:"La rareté a de la valeur : les défenseurs gauchers de qualité manquent cruellement dans cette cuvée, ce qui protège son rang malgré des chiffres modestes."}, |
|
372 |
+ {id:"harper", nom:"Levi Harper", position:"D", tir:"D", taille:"5'11\"", tailleCm:180, poids:174, naissance:"2008-10-03", nationalite:"USA", |
|
373 |
+ equipeActuelle:"Spirit de Saginaw", ligue:"OHL", |
|
374 |
+ stats:{mj:68,b:12,p:45,pts:57,plusMoins:null,moy:null,arr:null}, statsLigue:"OHL", |
|
375 |
+ rangsParSource:{wheeler:null,dfo:19,tank:28}, mentionWheeler:true, tendance:"up", risque:"moyen", sleeper:true, |
|
376 |
+ forces:["57 points en 68 matchs comme défenseur recrue OHL","Quart-arrière d'avantage numérique naturel","79 PIM : joue avec du mordant"], |
|
377 |
+ faiblesses:["Mention honorable seulement chez Wheeler","Couverture défensive à resserrer"], |
|
378 |
+ comparableLNH:"D offensif recrue-éclair, profil à la Ryan Merkley assagi (style, pas une promesse)", |
|
379 |
+ projectionPlafond:"Défenseur top-4 offensif", radar:{patinage:55,sensJeu:60,tir:50,competitivite:50,jeuDefensif:45}, |
|
380 |
+ analyse:"SLEEPER : 57 points comme D recrue en OHL, c'est une production de premier plan — l'écart entre ses chiffres et son rang consensus (19e-28e) est l'un des plus grands de la cuvée."}, |
|
381 |
+ {id:"calce", nom:"Max Calce", position:"C", tir:"n.d.", taille:"5'11\"", tailleCm:180, poids:181, naissance:"2009-06-11", nationalite:"GER", |
|
382 |
+ equipeActuelle:"Adler Mannheim", ligue:"DEL (Allemagne)", |
|
383 |
+ stats:{mj:14,b:2,p:0,pts:2,plusMoins:null,moy:null,arr:null}, statsLigue:"DEL (pro) — plus 23 pts en 17 MJ au U20", |
|
384 |
+ rangsParSource:{wheeler:null,dfo:13,tank:45,thn:6}, mentionWheeler:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
385 |
+ forces:["Meilleur buteur U18 d'Allemagne; 4 points en 5 matchs au Mondial U18 2026","19 min 27 s de temps de glace moyen au U18 mondial — usage massif","Déjà 14 matchs pros en DEL"], |
|
386 |
+ faiblesses:["Classé entre 6e (THN) et 45e (Tankathon) — l'écart le plus extrême de la cuvée","Échantillon contre sa propre cohorte encore mince"], |
|
387 |
+ comparableLNH:"Attaquant allemand polyvalent, profil à la Tim Stützle prudent (style, pas une promesse)", |
|
388 |
+ projectionPlafond:"Top-9 — fourchette exceptionnellement large", radar:{patinage:55,sensJeu:60,tir:55,competitivite:50,jeuDefensif:45}, |
|
389 |
+ analyse:"⚡ Le joueur le plus volatil de la cuvée : 6e chez The Hockey News, 45e chez Tankathon. Anciennement connu sous le nom de Max Penkin. Le meilleur espoir allemand depuis Stützle si la version THN est la bonne."}, |
|
390 |
+ {id:"gordoncarroll", nom:"Shaeffer Gordon-Carroll", position:"AD", tir:"n.d.", taille:"6'00\"", tailleCm:183, poids:190, naissance:"2008-11-26", nationalite:"USA", |
|
391 |
+ equipeActuelle:"Tigers de Medicine Hat", ligue:"WHL", |
|
392 |
+ stats:{mj:41,b:12,p:25,pts:37,plusMoins:null,moy:null,arr:null}, statsLigue:"WHL", |
|
393 |
+ rangsParSource:{wheeler:22,dfo:31,tank:22}, tendance:"stable", risque:"moyen", sleeper:false, |
|
394 |
+ forces:["37 points en 41 matchs avant une blessure — presque un point par match","Ailier intelligent qui joue plus grand que son gabarit","A représenté USA U18 au Hlinka-Gretzky d'août 2025 (nationalité USA confirmée)"], |
|
395 |
+ faiblesses:["Saison écourtée par blessure : échantillon réduit"], |
|
396 |
+ comparableLNH:"Ailier complémentaire productif, profil à la Seth Jarvis (style, pas une promesse)", |
|
397 |
+ projectionPlafond:"Ailier top-9", radar:{patinage:55,sensJeu:55,tir:55,competitivite:55,jeuDefensif:50}, |
|
398 |
+ analyse:"Son rythme avant blessure soutenait un rang plus élevé. Une saison santé à Medicine Hat, équipe puissante de la WHL, le stabilisera."}, |
|
399 |
+ {id:"glance", nom:"Jamie Glance", position:"AD", tir:"n.d.", taille:"5'11\"", tailleCm:180, poids:182, naissance:"2008-09-23", nationalite:"USA", |
|
400 |
+ equipeActuelle:"USNTDP U18 (destination 2026-27 incertaine)", ligue:"NTDP/USHL", |
|
401 |
+ stats:{mj:62,b:23,p:33,pts:56,plusMoins:null,moy:null,arr:null}, statsLigue:"NTDP U18", |
|
402 |
+ rangsParSource:{wheeler:null,dfo:27,tank:23}, mentionWheeler:true, tendance:"down", risque:"moyen", sleeper:false, |
|
403 |
+ forces:["56 points en 62 matchs avec le NTDP U18","Parmi les plus vieux de la cuvée : production contre du U18 déjà établie"], |
|
404 |
+ faiblesses:["Avenir 2026-27 incertain (départ possible vers la LHJMQ selon Daily Faceoff)","Doit élargir son jeu hors de l'avantage numérique"], |
|
405 |
+ comparableLNH:"Ailier marqueur d'occasion, profil à la Alex Tuch compact (style, pas une promesse)", |
|
406 |
+ projectionPlafond:"Ailier top-9", radar:{patinage:55,sensJeu:55,tir:60,competitivite:55,jeuDefensif:45}, |
|
407 |
+ analyse:"Production réelle, mais l'incertitude sur sa destination 2026-27 et la faiblesse collective du groupe NTDP le tirent vers le bas des classements d'été."}, |
|
408 |
+ {id:"edgar", nom:"Ryerson Edgar", position:"C", tir:"n.d.", taille:"5'10\"", tailleCm:178, poids:161, naissance:"2009-07-30", nationalite:"CAN", |
|
409 |
+ equipeActuelle:"IceDogs de Niagara", ligue:"OHL", |
|
410 |
+ stats:{mj:64,b:23,p:26,pts:49,plusMoins:null,moy:null,arr:null}, statsLigue:"OHL", |
|
411 |
+ rangsParSource:{wheeler:25,dfo:26,tank:26}, tendance:"stable", risque:"moyen", sleeper:false, |
|
412 |
+ forces:["49 points comme recrue OHL parmi les plus jeunes de la cuvée (né fin juillet 2009)","Moteur constant, bon en échec-avant","Engagement NCAA vers Michigan rapporté (Tankathon — non confirmé par une 2e source)"], |
|
413 |
+ faiblesses:["161 lb à développer","Doit devenir plus dangereux en possession prolongée"], |
|
414 |
+ comparableLNH:"Centre énergique, profil à la Yanni Gourde (style, pas une promesse)", |
|
415 |
+ projectionPlafond:"Centre top-9", radar:{patinage:60,sensJeu:55,tir:50,competitivite:55,jeuDefensif:45}, |
|
416 |
+ analyse:"Consensus remarquablement stable (25e-26e partout). Son âge (parmi les plus jeunes admissibles) lui donne plus de piste de croissance que la plupart des joueurs classés autour de lui."}, |
|
417 |
+ {id:"eshkawkogan", nom:"Kohyn Eshkawkogan", position:"D", tir:"D", taille:"5'11\"", tailleCm:180, poids:183, naissance:"2008-11-19", nationalite:"CAN", |
|
418 |
+ equipeActuelle:"67's d'Ottawa", ligue:"OHL", |
|
419 |
+ stats:{mj:68,b:8,p:45,pts:53,plusMoins:null,moy:null,arr:null}, statsLigue:"OHL", |
|
420 |
+ rangsParSource:{wheeler:24,dfo:30,tank:24}, tendance:"stable", risque:"moyen", sleeper:false, |
|
421 |
+ forces:["53 points en 68 matchs — équipe d'étoiles des recrues OHL 2025","D droitier créatif en sortie de zone","L'un des plus jeunes au camp Hlinka 2025"], |
|
422 |
+ faiblesses:["Couverture d'enclave à resserrer","Gabarit moyen pour les minutes difficiles"], |
|
423 |
+ comparableLNH:"D droitier offensif, profil à la Ethan Del Mastro inversé côté offensif (style, pas une promesse)", |
|
424 |
+ projectionPlafond:"Défenseur top-4", radar:{patinage:55,sensJeu:60,tir:45,competitivite:50,jeuDefensif:50}, |
|
425 |
+ analyse:"Un des trois défenseurs droitiers de l'OHL qui se disputent la fin de première ronde avec Harper — son avance : la constance sur 68 matchs."}, |
|
426 |
+ {id:"eklundaspe", nom:"Dorian Eklund Aspe", position:"C", tir:"n.d.", taille:"6'04\"", tailleCm:194, poids:209, naissance:"2009-02-04", nationalite:"SWE", |
|
427 |
+ equipeActuelle:"Djurgårdens IF U18", ligue:"U18 Nationell", |
|
428 |
+ stats:{mj:19,b:14,p:15,pts:29,plusMoins:null,moy:null,arr:null}, statsLigue:"U18 Nationell", |
|
429 |
+ rangsParSource:{wheeler:null,dfo:null,tank:27}, mentionWheeler:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
430 |
+ forces:["29 points en 19 matchs U18 avec un gabarit de 6'4\", 209 lb","Présent au Hlinka-Gretzky 2026 avec la Suède"], |
|
431 |
+ faiblesses:["Classé par une seule source (Tankathon 27e) — incertitude élevée","N'a pas encore joué au niveau J20"], |
|
432 |
+ comparableLNH:"Grand attaquant suédois en développement, profil à la Jonathan Lekkerimäki costaud (style, pas une promesse)", |
|
433 |
+ projectionPlafond:"Top-9 — évaluation précoce", radar:{patinage:50,sensJeu:50,tir:55,competitivite:60,jeuDefensif:50}, |
|
434 |
+ analyse:"Source unique : rang à prendre avec prudence. Le physique + la production U18 justifient la curiosité; la saison J20 2026-27 dira le reste."}, |
|
435 |
+ {id:"hartl", nom:"Michal Hartl", position:"C", tir:"n.d.", taille:"6'00\"", tailleCm:183, poids:190, naissance:"2009-06-11", nationalite:"CZE", |
|
436 |
+ equipeActuelle:"HC Kometa Brno U20", ligue:"Tchéquie U20", |
|
437 |
+ stats:{mj:31,b:21,p:14,pts:35,plusMoins:null,moy:null,arr:null}, statsLigue:"Czechia U20", |
|
438 |
+ rangsParSource:{wheeler:null,dfo:null,tank:29}, mentionWheeler:true, mentionDfo:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
439 |
+ forces:["21 buts en 31 matchs U20 tchèque (43 pts en 39 MJ tous niveaux)","Tir rapide en mouvement","Présent au Hlinka-Gretzky 2026 avec la Tchéquie"], |
|
440 |
+ faiblesses:["Classement ferme d'une seule source (Tankathon 29e)","Doit tester l'Extraliga ou l'Amérique du Nord"], |
|
441 |
+ comparableLNH:"Marqueur tchèque direct, profil à la Martin Necas ailier (style, pas une promesse)", |
|
442 |
+ projectionPlafond:"Ailier top-9", radar:{patinage:55,sensJeu:55,tir:60,competitivite:55,jeuDefensif:45}, |
|
443 |
+ analyse:"Mention honorable chez Wheeler et « also considered » chez Daily Faceoff : le 2e meilleur espoir tchèque derrière Tomek selon la plupart des lectures."}, |
|
444 |
+ {id:"wycisk", nom:"Jaakko Wycisk", position:"AD", tir:"D", taille:"6'01\"", tailleCm:185, poids:190, naissance:"2009-03-16", nationalite:"CAN", |
|
445 |
+ equipeActuelle:"Storm de Guelph", ligue:"OHL", |
|
446 |
+ stats:{mj:60,b:17,p:26,pts:43,plusMoins:null,moy:null,arr:null}, statsLigue:"OHL", |
|
447 |
+ rangsParSource:{wheeler:null,dfo:null,tank:30}, mentionWheeler:true, tendance:"up", risque:"moyen", sleeper:false, |
|
448 |
+ forces:["4 points (1B-3P) en demi-finale du Hlinka-Gretzky 2026 contre la Finlande, but en finale","43 points comme recrue OHL","Ailier honnête dans les trois zones"], |
|
449 |
+ faiblesses:["Classement ferme d'une seule source (Tankathon 30e)","Doit devenir le moteur offensif de Guelph pour grimper"], |
|
450 |
+ comparableLNH:"Ailier deux sens en progression, profil à la Mason Marchment jeune (style, pas une promesse)", |
|
451 |
+ projectionPlafond:"Ailier top-9", radar:{patinage:55,sensJeu:55,tir:55,competitivite:60,jeuDefensif:50}, |
|
452 |
+ analyse:"Parmi les meneurs canadiens du Hlinka 2026 (or) — le tournoi qui vient de se terminer a probablement fait grimper son nom sur les listes d'automne."}, |
|
453 |
+ /* --- Banque élargie : sleepers, chutes et fiches allégées --- */ |
|
454 |
+ {id:"scantlebury", nom:"James Scantlebury", position:"C", tir:"n.d.", taille:"5'10\"", tailleCm:178, poids:172, naissance:"2009-01-15", nationalite:"CAN", |
|
455 |
+ equipeActuelle:"Remparts de Québec (dès 2026-27, ex-Chicago Steel)", ligue:"LHJMQ", |
|
456 |
+ stats:{mj:62,b:16,p:23,pts:39,plusMoins:-6,moy:null,arr:null}, statsLigue:"USHL", |
|
457 |
+ rangsParSource:{wheeler:null,dfo:29,tank:32}, mentionWheeler:true, tendance:"up", risque:"moyen", sleeper:true, |
|
458 |
+ forces:["Meilleur pointeur U17 de toute la USHL en 2025-26 (devant Carter Meyer)","Première équipe des recrues USHL 2026","Québécois (Châteauguay) de retour dans la LHJMQ avec les Remparts"], |
|
459 |
+ faiblesses:["Classé seulement 29e-32e malgré sa production — d'où son statut de sleeper","Gabarit moyen (5'10\")"], |
|
460 |
+ comparableLNH:"Centre créatif sous-coté, profil à la Alex Newhook (style, pas une promesse)", |
|
461 |
+ projectionPlafond:"Centre top-9 avec plafond top-6", radar:{patinage:55,sensJeu:60,tir:50,competitivite:55,jeuDefensif:50}, |
|
462 |
+ analyse:"SLEEPER no 1 : dominer les U17 de la USHL devant Meyer et n'être classé que 29e-32e, c'est l'écart production/rang le plus flagrant de la cuvée. Une grosse saison à Québec le fera exploser sur les listes."}, |
|
463 |
+ {id:"naudins", nom:"Roberts Naudiņš", position:"AG", tir:"n.d.", taille:"6'06\"", tailleCm:199, poids:208, naissance:"2008-11-18", nationalite:"LVA", |
|
464 |
+ equipeActuelle:"Vees de Penticton (dès 2026-27, ex-Shattuck-St. Mary's)", ligue:"WHL", |
|
465 |
+ stats:{mj:51,b:24,p:50,pts:74,plusMoins:null,moy:null,arr:null}, statsLigue:"USHS-Prep", |
|
466 |
+ rangsParSource:{wheeler:null,dfo:null,tank:34}, mentionWheeler:true, mentionDfo:true, tendance:"stable", risque:"élevé", sleeper:true, |
|
467 |
+ forces:["Plus grand joueur de la cuvée (6'6\") avec 74 points en 51 matchs","Mains souples pour son gabarit","Saut vers la WHL (Penticton) en 2026-27"], |
|
468 |
+ faiblesses:["Production réalisée au niveau préparatoire (Shattuck) — vraie référence à venir","Coordination/patinage en croissance, comme tous les géants"], |
|
469 |
+ comparableLNH:"Géant letton offensif, profil à la Zemgus Girgensons offensif (style, pas une promesse)", |
|
470 |
+ projectionPlafond:"Ailier top-9 à haut plafond", radar:{patinage:45,sensJeu:55,tir:55,competitivite:55,jeuDefensif:45}, |
|
471 |
+ analyse:"SLEEPER : le profil physique le plus rare de la cuvée. Si la production suit à Penticton (WHL), il ne restera pas longtemps en fin de classement."}, |
|
472 |
+ {id:"yermolov", nom:"Daniil Yermolov", position:"AG", tir:"n.d.", taille:"6'02\"", tailleCm:188, poids:183, naissance:"2009-02-15", nationalite:"RUS", |
|
473 |
+ equipeActuelle:"Krasnaya Armiya Moskva (CSKA jr)", ligue:"MHL (Russie)", |
|
474 |
+ stats:{mj:null,b:null,p:null,pts:null,plusMoins:null,moy:null,arr:null}, statsLigue:"MHL — ligne complète n.d.", |
|
475 |
+ rangsParSource:{wheeler:null,dfo:null,tank:38}, mentionWheeler:true, tendance:"stable", risque:"élevé", sleeper:true, |
|
476 |
+ forces:["Considéré par Wheeler comme un des grands talents bruts de la cuvée","Ailier de 6'2\" avec des flashs de haut niveau"], |
|
477 |
+ faiblesses:["Échantillon MHL jugé trop mince par Wheeler pour le classer","Ligne statistique 2025-26 complète introuvable (n.d.)"], |
|
478 |
+ comparableLNH:"Talent brut russe, comparable prématuré (n.d.)", |
|
479 |
+ projectionPlafond:"n.d. — trop tôt", radar:null, |
|
480 |
+ analyse:"SLEEPER à haut risque : Wheeler écrit qu'il a le talent du top de la cuvée, sans le classer faute de matchs. Le nom à surveiller dès l'ouverture de la MHL."}, |
|
481 |
+ {id:"kolmakov", nom:"Ilya Kolmakov", position:"AG", tir:"G", taille:"6'01\"", tailleCm:185, poids:165, naissance:"2008-09-30", nationalite:"RUS", |
|
482 |
+ equipeActuelle:"Phoenix de Sherbrooke", ligue:"LHJMQ", |
|
483 |
+ stats:{mj:62,b:13,p:35,pts:48,plusMoins:null,moy:null,arr:null}, statsLigue:"LHJMQ", |
|
484 |
+ rangsParSource:{}, listeEP:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:true, |
|
485 |
+ forces:["48 points comme recrue LHJMQ — non classé par les grandes listes","Passeur naturel (35 aides)"], |
|
486 |
+ faiblesses:["Absent de tous les classements numérotés — seulement la liste de surveillance d'Elite Prospects","Données physiques introuvables (n.d.)"], |
|
487 |
+ comparableLNH:"n.d.", |
|
488 |
+ projectionPlafond:"n.d. — hors classements", radar:null, |
|
489 |
+ analyse:"SLEEPER : près de 50 points dans la LHJMQ sans même figurer aux classements d'été. Le genre de nom que la Centrale de recrutement ajoutera dès sa liste préliminaire d'automne."}, |
|
490 |
+ {id:"murata", nom:"Charlie Murata", position:"AD", tir:"n.d.", taille:"6'00\"", tailleCm:183, poids:183, naissance:"2009-02-15", nationalite:"CAN", |
|
491 |
+ equipeActuelle:"Firebirds de Flint", ligue:"OHL", |
|
492 |
+ stats:{mj:59,b:5,p:13,pts:18,plusMoins:null,moy:null,arr:null}, statsLigue:"OHL", |
|
493 |
+ rangsParSource:{wheeler:null,tank:41,button:4}, mentionWheeler:true, tendance:"down", risque:"élevé", sleeper:false, |
|
494 |
+ forces:["Talent reconnu tôt : 4e du lookahead TSN/Button en novembre 2025","Engagé avec Michigan State (NCAA)"], |
|
495 |
+ faiblesses:["Saison OHL très décevante : 18 points en 59 matchs","Chute de 4e (nov. 2025) à 41e (été 2026) — la plus forte de la cuvée"], |
|
496 |
+ comparableLNH:"n.d. — projection suspendue à son rebond", |
|
497 |
+ projectionPlafond:"À rebâtir", radar:null, |
|
498 |
+ analyse:"⚡ EN CHUTE : personne n'a perdu plus de valeur en huit mois. Le talent qui séduisait Button en début de saison existe encore ; Flint devra lui donner le volume pour le prouver. Retenu par Équipe Canada au Hlinka 2026 (2 passes en 4 matchs — nationalité CAN confirmée par le tableau officiel du tournoi)."}, |
|
499 |
+ {id:"selic", nom:"Tomas Selic", position:"AD", tir:"G", taille:"6'03\"", tailleCm:191, poids:198, naissance:"2009-05-08", nationalite:"SVK", |
|
500 |
+ equipeActuelle:"HC Kometa Brno U20", ligue:"Tchéquie U20", |
|
501 |
+ stats:{mj:45,b:21,p:29,pts:50,plusMoins:null,moy:null,arr:null}, statsLigue:"Czechia U20", |
|
502 |
+ rangsParSource:{}, listeEP:true, sourceUnique:true, tendance:"up", risque:"élevé", sleeper:false, |
|
503 |
+ forces:["Co-meneur des pointeurs du Hlinka-Gretzky 2026 : 5B-3P en 4 matchs avec la Slovaquie","50 points en 45 matchs au U20 tchèque en 2025-26"], |
|
504 |
+ faiblesses:["Absent de tous les classements numérotés d'été (liste de surveillance EP seulement)","Données physiques et de naissance introuvables (n.d.)"], |
|
505 |
+ comparableLNH:"n.d.", |
|
506 |
+ projectionPlafond:"n.d. — à reclasser après son tournoi", radar:null, |
|
507 |
+ analyse:"Ajouté à la banque après le Hlinka 2026 : finir premier pointeur du tournoi à égalité (8 pts) sans figurer sur aucune liste d'été, c'est le profil type du joueur que les classements d'automne feront bondir. Bémol du sommaire officiel : blanchi au match de bronze (défaite 3-2) avec 2 pénalités en 1re période (rudesse, conduite antisportive). Le meilleur Slovaque de la cuvée avec Kazda."}, |
|
508 |
+ {id:"pelosi", nom:"Rocco Pelosi", position:"C", tir:"n.d.", taille:"5'11\"", tailleCm:180, poids:176, naissance:"2009-01-28", nationalite:"USA", |
|
509 |
+ equipeActuelle:"USNTDP (U18 en 2026-27)", ligue:"NTDP/USHL", |
|
510 |
+ stats:{mj:53,b:11,p:11,pts:22,plusMoins:-23,moy:null,arr:null}, statsLigue:"NTDP U17", |
|
511 |
+ rangsParSource:{wheeler:null,dfo:25,tank:42}, mentionWheeler:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
512 |
+ forces:["Frère cadet de Chris Pelosi (Bruins)","Centre responsable utilisé dans toutes les situations"], |
|
513 |
+ faiblesses:["Production U17 modeste (22 pts) et -23","Fourchette 25e-42e"], |
|
514 |
+ comparableLNH:"n.d.", projectionPlafond:"Centre de soutien", radar:null, |
|
515 |
+ analyse:"Fourchette large (25e chez Daily Faceoff, 42e chez Tankathon) : le profil « identité » séduit certains recruteurs plus que d'autres."}, |
|
516 |
+ {id:"johnsson", nom:"Douglas Johnsson", position:"D", tir:"D", taille:"5'10\"", tailleCm:178, poids:163, naissance:"2009-07-01", nationalite:"SWE", |
|
517 |
+ equipeActuelle:"Skellefteå AIK U20", ligue:"J20 Nationell", |
|
518 |
+ stats:{mj:12,b:3,p:9,pts:12,plusMoins:null,moy:null,arr:null}, statsLigue:"J20", |
|
519 |
+ rangsParSource:{wheeler:null,dfo:32,tank:33}, mentionWheeler:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
520 |
+ forces:["Un point par match en J20 comme défenseur de 16 ans","Production « superbe à tous les niveaux » (Daily Faceoff)"], |
|
521 |
+ faiblesses:["163 lb — gabarit à construire","12 matchs J20 seulement"], |
|
522 |
+ comparableLNH:"n.d.", projectionPlafond:"Défenseur top-4 si le physique suit", radar:null, |
|
523 |
+ analyse:"Le D suédois le mieux considéré de la cuvée pour l'instant, tout juste derrière la première ronde projetée."}, |
|
524 |
+ {id:"mcgregor", nom:"Kaden McGregor", position:"C", tir:"D", taille:"5'11\"", tailleCm:180, poids:181, naissance:"2009-01-30", nationalite:"CAN", |
|
525 |
+ equipeActuelle:"Petes de Peterborough", ligue:"OHL", |
|
526 |
+ stats:{mj:39,b:7,p:13,pts:20,plusMoins:null,moy:null,arr:null}, statsLigue:"OHL", |
|
527 |
+ rangsParSource:{wheeler:null,tank:35}, mentionWheeler:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
528 |
+ forces:["Outillage offensif au-dessus de sa production"], faiblesses:["20 points en 39 matchs — doit produire"], |
|
529 |
+ comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, |
|
530 |
+ analyse:"Fiche allégée — données limitées (source de classement unique)."}, |
|
531 |
+ {id:"walos", nom:"Easton Walos", position:"C", tir:"G", taille:"5'11\"", tailleCm:180, poids:174, naissance:"2008-12-28", nationalite:"USA", |
|
532 |
+ equipeActuelle:"Sting de Sarnia", ligue:"OHL", |
|
533 |
+ stats:{mj:68,b:25,p:23,pts:48,plusMoins:null,moy:null,arr:null}, statsLigue:"OHL", |
|
534 |
+ rangsParSource:{wheeler:null,tank:36}, mentionWheeler:true, sourceUnique:true, tendance:"stable", risque:"moyen", sleeper:false, |
|
535 |
+ forces:["25 buts comme recrue OHL"], faiblesses:["Création pour les autres plus limitée"], |
|
536 |
+ comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, |
|
537 |
+ analyse:"Fiche allégée — données limitées (source de classement unique)."}, |
|
538 |
+ {id:"conboy", nom:"Gunnar Conboy", position:"C", tir:"n.d.", taille:"6'04\"", tailleCm:193, poids:201, naissance:"2009-04-02", nationalite:"USA", |
|
539 |
+ equipeActuelle:"Gamblers de Green Bay", ligue:"USHL", |
|
540 |
+ stats:{mj:37,b:12,p:9,pts:21,plusMoins:null,moy:null,arr:null}, statsLigue:"USHL", |
|
541 |
+ rangsParSource:{wheeler:null,tank:37}, mentionWheeler:true, sourceUnique:true, tendance:"up", risque:"élevé", sleeper:false, |
|
542 |
+ forces:["Centre de 6'4\" ; seul but américain en finale du Hlinka-Gretzky 2026"], faiblesses:["Production USHL encore modeste"], |
|
543 |
+ comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, |
|
544 |
+ analyse:"Fiche allégée. Son but en finale du Hlinka (8 août 2026) le met sur le radar de l'automne."}, |
|
545 |
+ {id:"savin", nom:"Daniil Savin", position:"C", tir:"n.d.", taille:"6'00\"", tailleCm:183, poids:163, naissance:"2009-02-18", nationalite:"RUS", |
|
546 |
+ equipeActuelle:"Akademiya SKA St-Pétersbourg", ligue:"MHL (Russie)", |
|
547 |
+ stats:{mj:43,b:11,p:13,pts:24,plusMoins:null,moy:null,arr:null}, statsLigue:"MHL", |
|
548 |
+ rangsParSource:{wheeler:null,tank:39}, mentionWheeler:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
549 |
+ forces:["Cité en mention honorable par Wheeler"], faiblesses:["Production MHL modeste"], |
|
550 |
+ comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, analyse:"Fiche allégée — données limitées."}, |
|
551 |
+ {id:"kuukasjarvi", nom:"Roni Kuukasjärvi", position:"D", tir:"D", taille:"6'01\"", tailleCm:185, poids:165, naissance:"2009-04-08", nationalite:"FIN", |
|
552 |
+ equipeActuelle:"Ilves U20", ligue:"U20 SM-sarja", |
|
553 |
+ stats:{mj:34,b:0,p:14,pts:14,plusMoins:null,moy:null,arr:null}, statsLigue:"U20 SM-sarja", |
|
554 |
+ rangsParSource:{wheeler:null,tank:40}, mentionWheeler:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
555 |
+ forces:["D droitier finlandais mobile","But gagnant du match de bronze au Hlinka 2026 (AN) + 1 passe"], faiblesses:["Aucun but en 34 matchs U20 en 2025-26"], |
|
556 |
+ comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, analyse:"Fiche allégée. Son but gagnant en avantage numérique dans le match pour le bronze (13:27 de la 3e, Finlande 3-2 Slovaquie) est exactement le genre de moment qui fait apparaître un nom sur les listes d'automne."}, |
|
557 |
+ {id:"sundberg", nom:"Oliver Sundberg", position:"AD", tir:"n.d.", taille:"6'00\"", tailleCm:183, poids:174, naissance:"2009-01-10", nationalite:"SWE", |
|
558 |
+ equipeActuelle:"Djurgårdens IF U18", ligue:"U18 Nationell", |
|
559 |
+ stats:{mj:18,b:10,p:19,pts:29,plusMoins:null,moy:null,arr:null}, statsLigue:"U18 (18-29 selon EP; Tankathon rapporte 22 MJ, 33 pts — fourchette)", |
|
560 |
+ rangsParSource:{wheeler:null,tank:43}, mentionWheeler:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
561 |
+ forces:["Plus d'un point et demi par match au U18 suédois"], faiblesses:["Niveau J20 pas encore testé"], |
|
562 |
+ comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, analyse:"Fiche allégée — données limitées (les deux sources de stats divergent légèrement, fourchette affichée)."}, |
|
563 |
+ {id:"sears", nom:"Finnegan Sears", position:"AG", tir:"n.d.", taille:"6'00\"", tailleCm:183, poids:187, naissance:"2009-05-04", nationalite:"USA", |
|
564 |
+ equipeActuelle:"USNTDP (U18 en 2026-27)", ligue:"NTDP/USHL", |
|
565 |
+ stats:{mj:null,b:null,p:null,pts:null,plusMoins:null,moy:null,arr:null}, statsLigue:"NTDP — ligne complète n.d.", |
|
566 |
+ rangsParSource:{wheeler:null,tank:44}, mentionWheeler:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
567 |
+ forces:["Mention honorable Wheeler"], faiblesses:["Ligne statistique 2025-26 complète introuvable (n.d.)"], |
|
568 |
+ comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, analyse:"Fiche allégée — données limitées."}, |
|
569 |
+ {id:"daley", nom:"Trevor Daley Jr.", position:"AG", tir:"n.d.", taille:"5'09\"", tailleCm:175, poids:185, naissance:"2009-06-11", nationalite:"USA", |
|
570 |
+ equipeActuelle:"Greyhounds de Soo (dès 2026-27, ex-NTDP)", ligue:"OHL", |
|
571 |
+ stats:{mj:4,b:0,p:1,pts:1,plusMoins:0,moy:null,arr:null}, statsLigue:"NTDP U17 (saison très limitée)", |
|
572 |
+ rangsParSource:{wheeler:null,tank:46}, mentionWheeler:true, mentionDfo:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
573 |
+ forces:["Fils de l'ex-défenseur LNH Trevor Daley"], faiblesses:["4 matchs joués en 2025-26 — échantillon quasi nul"], |
|
574 |
+ comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, analyse:"Fiche allégée — saison 2025-26 très limitée, relance attendue à Soo (OHL)."}, |
|
575 |
+ {id:"forsberg", nom:"Wiggo Forsberg", position:"C", tir:"n.d.", taille:"6'00\"", tailleCm:184, poids:168, naissance:"2009-06-11", nationalite:"SWE", |
|
576 |
+ equipeActuelle:"Frölunda HC U18", ligue:"U18 Nationell", |
|
577 |
+ stats:{mj:19,b:9,p:23,pts:32,plusMoins:null,moy:null,arr:null}, statsLigue:"U18 Nationell", |
|
578 |
+ rangsParSource:{wheeler:null,tank:47}, mentionWheeler:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
579 |
+ forces:["Passeur productif au U18 suédois"], faiblesses:["Niveau J20 pas encore testé"], |
|
580 |
+ comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, analyse:"Fiche allégée — données limitées."}, |
|
581 |
+ {id:"kachlir", nom:"Lukáš Kachlíř", position:"D", tir:"D", taille:"5'08\"", tailleCm:173, poids:150, naissance:"2009-09-05", nationalite:"CZE", |
|
582 |
+ equipeActuelle:"Bílí Tygři Liberec U20", ligue:"Tchéquie U20", |
|
583 |
+ stats:{mj:29,b:6,p:21,pts:27,plusMoins:null,moy:null,arr:null}, statsLigue:"Czechia U20", |
|
584 |
+ rangsParSource:{}, mentionWheeler:true, mentionDfo:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
585 |
+ forces:["Wheeler : « un des meilleurs joueurs de sa cohorte »","4 points en 4 matchs au Hlinka précédent"], |
|
586 |
+ faiblesses:["5'8\", 150 lb — le plus petit joueur suivi de la cuvée; la taille limite sa projection"], |
|
587 |
+ comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, analyse:"Aucun rang numérique : mentions seulement (Wheeler MH, DFO « also considered »)."}, |
|
588 |
+ {id:"litalien", nom:"Malik L'Italien", position:"D", tir:"n.d.", taille:"n.d.", tailleCm:null, poids:null, naissance:"n.d.", nationalite:"CAN", |
|
589 |
+ equipeActuelle:"Mooseheads de Halifax", ligue:"LHJMQ", |
|
590 |
+ stats:{mj:64,b:null,p:null,pts:24,plusMoins:null,moy:null,arr:null}, statsLigue:"LHJMQ (24 pts — répartition B/P n.d.)", |
|
591 |
+ rangsParSource:{}, listeEP:true, sourceUnique:true, tendance:"up", risque:"élevé", sleeper:false, |
|
592 |
+ forces:["Retenu par Équipe Canada au Hlinka 2026 (or) sans figurer sur aucun classement","1 but et 1 passe en demi-finale contre la Finlande, puis une passe sur un but en finale","24 points comme défenseur recrue LHJMQ"], |
|
593 |
+ faiblesses:["Absent de tous les classements numérotés d'été","Données physiques introuvables (n.d.)"], |
|
594 |
+ comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, |
|
595 |
+ analyse:"Ajouté après le Hlinka 2026 : être choisi par Hockey Canada puis produire dans les matchs de médailles (sommaires officiels) sans être classé nulle part, c'est un profil de « riser » d'automne. Parmi les joueurs « tendance » d'Elite Prospects en août 2026."}, |
|
596 |
+ /* --- Gardiens à surveiller (aucune source ne classe de gardien 2027 — |
|
597 |
+ stats réelles retrouvées dans les bases publiques le 2026-08-08) --- */ |
|
598 |
+ {id:"deniger", nom:"Patrick Déniger", position:"G", tir:"n.d.", taille:"6'02\"", tailleCm:188, poids:190, naissance:"2008-10-02", nationalite:"CAN", |
|
599 |
+ equipeActuelle:"Remparts de Québec", ligue:"LHJMQ", |
|
600 |
+ stats:{mj:30,b:null,p:null,pts:null,plusMoins:null,moy:2.33,arr:0.910}, statsLigue:"LHJMQ", |
|
601 |
+ rangsParSource:{}, listeEP:true, sourceUnique:true, tendance:"up", risque:"élevé", sleeper:false, |
|
602 |
+ forces:["Fiche 18-9-3, MOY 2,33 et ,910 comme recrue LHJMQ (hockeydb/chl.ca, recoupé 4 sources)","Cité par The Hockey News parmi les 5 joueurs LHJMQ à suivre pour 2027","A porté les couleurs de Canada U18 en 2025-26"], |
|
603 |
+ faiblesses:["Aucune source ne classe de gardien 2027 pour l'instant","Séries plus difficiles : 2,53 et ,902 en 10 matchs"], |
|
604 |
+ comparableLNH:"n.d.", projectionPlafond:"n.d. — les gardiens se classent tard", radar:null, |
|
605 |
+ analyse:"Le meilleur candidat québécois chez les gardiens 2027. Données retrouvées dans les bases publiques (hockeydb, chl.ca, PuckPedia, QuantHockey) alors que les classements d'été ignorent tous les gardiens."}, |
|
606 |
+ {id:"vetrov", nom:"Yaroslav Vetrov", position:"G", tir:"n.d.", taille:"6'02\"", tailleCm:188, poids:183, naissance:"2009-01-12", nationalite:"RUS", |
|
607 |
+ equipeActuelle:"Sibirskie Snaipery Novosibirsk", ligue:"MHL (Russie)", |
|
608 |
+ stats:{mj:31,b:null,p:null,pts:null,plusMoins:null,moy:1.85,arr:0.919}, statsLigue:"MHL", |
|
609 |
+ rangsParSource:{}, listeEP:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
610 |
+ forces:["MOY 1,85 et ,919 en 31 matchs (site officiel MHL)","Décrit comme « un des meilleurs gardiens de toute la MHL » (D. Griffing, juin 2026)","Play-ins : ,946 en 2 matchs"], |
|
611 |
+ faiblesses:["Facteur russe : visibilité et calendrier incertains","11e des Russes nés en 2009 selon Griffing"], |
|
612 |
+ comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, |
|
613 |
+ analyse:"Statistiquement le gardien 2027 le plus dominant retrouvé — 1,85 de moyenne dans la MHL à 16-17 ans. Source : engmhl.khl.ru (575 arrêts, 51 buts contre)."}, |
|
614 |
+ {id:"nikolaev", nom:"Andrei Nikolaev", position:"G", tir:"n.d.", taille:"6'04\"", tailleCm:194, poids:165, naissance:"2009-06-03", nationalite:"RUS", |
|
615 |
+ equipeActuelle:"Jr. Titans du New Jersey", ligue:"NAHL", |
|
616 |
+ stats:{mj:22,b:null,p:null,pts:null,plusMoins:null,moy:2.53,arr:0.914}, statsLigue:"NAHL", |
|
617 |
+ rangsParSource:{}, listeEP:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
618 |
+ forces:["Gardien du mois NAHL en novembre 2025 (2,04 / ,929)","6'4\" — gabarit moderne","Engagé avec Boston University (NCAA)"], |
|
619 |
+ faiblesses:["165 lb à étoffer","Fiche divergente selon les sources (12-7-1 hockeydb vs 12-6 NAHL) — fourchette"], |
|
620 |
+ comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, |
|
621 |
+ analyse:"Ligne complète reconstituée des bases publiques : 2,53 / ,914 (513 arrêts sur 561 tirs, 3 blanchissages). Orthographié « Nikolayev » chez Elite Prospects."}, |
|
622 |
+ {id:"nikitins", nom:"Iļja Ņikitins", position:"G", tir:"n.d.", taille:"6'00\"", tailleCm:183, poids:171, naissance:"n.d.", nationalite:"LVA", |
|
623 |
+ equipeActuelle:"Rebels de Philadelphie", ligue:"NAHL", |
|
624 |
+ stats:{mj:40,b:null,p:null,pts:null,plusMoins:null,moy:2.85,arr:0.910}, statsLigue:"NAHL", |
|
625 |
+ rangsParSource:{}, listeEP:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
626 |
+ forces:["40 matchs — la plus grosse charge de travail des gardiens 2027 recensés",",910 malgré une équipe faible (fiche 14-20)"], |
|
627 |
+ faiblesses:["1 seul blanchissage","Date de naissance exacte introuvable (n.d.)"], |
|
628 |
+ comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, |
|
629 |
+ analyse:"Fiche allégée — source : nahl.com (2,847 / ,910). Sur le portail des gardiens 2027 d'Elite Prospects."}, |
|
630 |
+ {id:"salenforsberg", nom:"Vilmer Salén Forsberg", position:"G", tir:"n.d.", taille:"6'06\"", tailleCm:197, poids:220, naissance:"2009-08-21", nationalite:"SWE", |
|
631 |
+ equipeActuelle:"Bulldogs de Brantford (dès 2026-27, ex-Södertälje)", ligue:"OHL", |
|
632 |
+ stats:{mj:18,b:null,p:null,pts:null,plusMoins:null,moy:null,arr:0.898}, statsLigue:"U18 Nationell (,898; J20 : 5 MJ, 2,48, ,890)", |
|
633 |
+ rangsParSource:{}, listeEP:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
634 |
+ forces:["6'6\" et 220 lb — le plus grand gardien de la cuvée","Signé par Brantford (OHL) pour 2026-27","A pris le filet suédois au Hlinka 2026"], |
|
635 |
+ faiblesses:["Hlinka difficile : 4,59 / ,897 en 3 matchs (Suède 7e)","Chiffres U18/J20 encore modestes"], |
|
636 |
+ comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, |
|
637 |
+ analyse:"Le pari physique chez les gardiens 2027. Son passage dans l'OHL le mettra sous les radars nord-américains dès octobre."}, |
|
638 |
+ {id:"kokkonen", nom:"Lenni Kokkonen", position:"D", tir:"D", taille:"6'02\"", tailleCm:189, poids:190, naissance:"2009-03-25", nationalite:"FIN", |
|
639 |
+ equipeActuelle:"Kärpät U20", ligue:"U20 SM-sarja", |
|
640 |
+ stats:{mj:27,b:0,p:4,pts:4,plusMoins:null,moy:null,arr:null}, statsLigue:"U20 SM-sarja", |
|
641 |
+ rangsParSource:{}, mentionDfo:true, tendance:"stable", risque:"élevé", sleeper:false, |
|
642 |
+ forces:["Profil défensif pur cité par Daily Faceoff","3 passes au Hlinka 2026 (2 en demi-finale contre le Canada, 1 au match de bronze victorieux)"], faiblesses:["4 points en 27 matchs U20 en 2025-26"], |
|
643 |
+ comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, analyse:"Fiche allégée — mention « also considered » de Daily Faceoff, mais 5 points en 3 matchs au tableau du Hlinka (22e pointeur) pour un défenseur « défensif » : à resuivre à l'automne. Médaillé de bronze."}, |
|
644 |
+]; |
|
645 |
+ |
|
646 |
+/* ============================================================ |
|
647 |
+ CONSENSUS — moyenne pondérée des rangs numériques, écart-type |
|
648 |
+ échantillonnal (volatil si > 8), calculés au chargement. |
|
649 |
+ ============================================================ */ |
|
650 |
+/* Ajustements Coupe Hlinka-Gretzky 2026 (Edmonton, 3-8 août — terminée le |
|
651 |
+ jour de la génération). Performances individuelles SOURCÉES seulement, |
|
652 |
+ bornées à ±3 rangs, appliquées à la moyenne pondérée et affichées dans la |
|
653 |
+ fiche (rang brut → rang ajusté). Aucun malus individuel : aucun fait |
|
654 |
+ négatif individuel sourcé pour les joueurs de la banque. */ |
|
655 |
+const AJUSTEMENTS_HLINKA = { |
|
656 |
+ dupont: {aj:-1.0, fait:"Capitaine du Canada médaillé d'or; 1 but en demi-finale puis 4 passes en finale (sommaire officiel hlinkagretzkycup.ca — Sportsnet en rapportait 3 par erreur), meneur du match pour l'or", source:"Sommaires officiels hlinkagretzkycup.ca (matchs 5722/5726) · TSN/PC, 2026-08-08"}, |
|
657 |
+ joseph: {aj:+1.0, fait:"Or comme assistant-capitaine, mais production discrète pour son statut de no 2 : 1B-2P en 4 matchs — 43e pointeur du tournoi et 9e de son équipe, derrière Stroeder (8), Wycisk (8), Schultz (7), Veitch (6), Pue (6), Edgar (5), Cripps (5) et DuPont (4)", source:"Elite Prospects (stats officielles 2026-27), consulté 2026-08-08"}, |
|
658 |
+ england: {aj:-1.5, fait:"2B-1P au tableau officiel (4 matchs) puis 2 buts dans la finale gagnée 8-1 contre les États-Unis", source:"Elite Prospects · TSN/PC · Sportsnet, 2026-08-08"}, |
|
659 |
+ sundstrom:{aj:-1.0, fait:"2B-3P en 3 matchs (1,67 pt/match) dont le but en prolongation contre la Slovaquie; désigné meilleur joueur de la Suède au tournoi", source:"Elite Prospects · Daily Faceoff (jour 3), 2026-08-06/08"}, |
|
660 |
+ wycisk: {aj:-2.0, fait:"4e pointeur du tournoi (8 pts au tableau) : 1B-3P en demi-finale contre la Finlande puis 1B-1P en finale (passe sur le 2e but d'England + but à 12:15 de la 3e)", source:"Sommaires officiels hlinkagretzkycup.ca · Elite Prospects · CHL.ca, 2026-08-08"}, |
|
661 |
+ edgar: {aj:-1.0, fait:"3B-2P en 4 matchs — 19e pointeur du tournoi et 6e de l'équipe canadienne", source:"Elite Prospects (stats officielles 2026-27), consulté 2026-08-08"}, |
|
662 |
+ cripps: {aj:-0.5, fait:"1B-4P en 4 matchs — meilleur pointeur des défenseurs canadiens (devant DuPont au tableau officiel)", source:"Elite Prospects (stats officielles 2026-27), consulté 2026-08-08"}, |
|
663 |
+ neuenschwander:{aj:-1.0, fait:"3B-3P en 4 matchs — 13e pointeur du tournoi avec la Suisse", source:"Elite Prospects (stats officielles 2026-27), consulté 2026-08-08"}, |
|
664 |
+ conboy: {aj:-0.5, fait:"1 passe en demi-finale puis le seul but américain de la finale (avantage numérique) — nommé joueur du match des États-Unis", source:"Sommaires officiels hlinkagretzkycup.ca · USA Hockey · TSN/PC, 2026-08-08"}, |
|
665 |
+ santala: {aj:-0.5, fait:"Fort dans les matchs de médailles : 1 passe en demi-finale contre le Canada puis 1B-1P dans la victoire de bronze de la Finlande (3-2 vs Slovaquie)", source:"Sommaires officiels hlinkagretzkycup.ca (matchs 5722/5724), 2026-08-08"}, |
|
666 |
+ kuukasjarvi:{aj:-0.5, fait:"But GAGNANT du match pour la médaille de bronze (avantage numérique, 13:27 de la 3e) plus une passe sur le but de Santala", source:"Sommaire officiel hlinkagretzkycup.ca (match 5724), 2026-08-08"}, |
|
667 |
+}; |
|
668 |
+ESPOIRS.forEach(e => { |
|
669 |
+ const rangs = SOURCES.filter(s => Number.isFinite(e.rangsParSource[s.cle])); |
|
670 |
+ e.hlinka = AJUSTEMENTS_HLINKA[e.id] || null; |
|
671 |
+ if (rangs.length === 0) { e.rangConsensus = null; e.rangConsensusBrut = null; e.ecartType = null; e.volatil = false; return; } |
|
672 |
+ const poidsTotal = rangs.reduce((a,s)=>a+s.poids,0); |
|
673 |
+ e.rangConsensusBrut = rangs.reduce((a,s)=>a + s.poids*e.rangsParSource[s.cle],0) / poidsTotal; |
|
674 |
+ e.rangConsensus = Math.max(1, e.rangConsensusBrut + (e.hlinka ? e.hlinka.aj : 0)); |
|
675 |
+ const vals = rangs.map(s=>e.rangsParSource[s.cle]); |
|
676 |
+ if (vals.length >= 2) { |
|
677 |
+ const m = vals.reduce((a,b)=>a+b,0)/vals.length; |
|
678 |
+ e.ecartType = Math.sqrt(vals.reduce((a,v)=>a+(v-m)*(v-m),0)/(vals.length-1)); |
|
679 |
+ } else { e.ecartType = null; e.sourceUnique = true; } |
|
680 |
+ e.volatil = e.ecartType !== null && e.ecartType > 8; |
|
681 |
+ e.fourchette = [Math.min(...vals), Math.max(...vals)]; |
|
682 |
+}); |
|
683 |
+const parId = Object.fromEntries(ESPOIRS.map(e=>[e.id,e])); |
|
684 |
+ |
|
685 |
+/* Tableau éditorial : ordre de sélection des joueurs (choix 1 → 32). |
|
686 |
+ Suit le consensus, ajusté par les besoins organisationnels (Phase E). */ |
|
687 |
+const ORDRE_EDITORIAL = ["dupont","privalov","joseph","meyer","skvortsov","england","sundstrom","nelson","zhilkin","jacobson","neuenschwander","yakunin","cripps","pustovoy","kazda","santala","tomek","fitzhenry","meijer","shtyrkhunov","davidson","gutierrez","harper","tait","calce","glance","gordoncarroll","edgar","eshkawkogan","eklundaspe","hartl","wycisk"]; |
|
688 |
+ |
|
689 |
+/* Logique de chaque choix pour l'ORDRE DE BASE (pré-loterie) + plans B. */ |
|
690 |
+const LOGIQUES_BASE = { |
|
691 |
+ 1:{j:"dupont", txt:"Pire fiche 2025-26, Vancouver a besoin d'un joueur de concession : DuPont est le no 1 quasi unanime et le pool des Canucks manque justement de quantité et d'élite. Meilleur joueur disponible et besoin parfaitement alignés.", b:["joseph","privalov"]}, |
|
692 |
+ 2:{j:"privalov", txt:"La meilleure banque de la LNH (Wheeler) peut absorber le plus grand risque de la cuvée : Privalov, talent de top-2 (2e chez Daily Faceoff et Tankathon), passe devant Joseph dans notre consensus ajusté après le Hlinka discret de ce dernier. Son contrat KHL jusqu'en 2030 est exactement le pari de luxe qu'une organisation qui regorge d'espoirs peut se permettre.", b:["joseph","meyer"]}, |
|
693 |
+ 3:{j:"joseph", txt:"Les Rangers manquent de centres offensifs d'élite : Joseph, centre de 6'4\" point-par-match comme recrue de 16 ans dans la LHJMQ, reste un talent de top-2 sur papier. Son Hlinka discret (1B-2P en 4 matchs, 43e pointeur) le fait glisser d'un rang dans le consensus ajusté — au 3e rang, c'est la valeur qui rencontre le besoin.", b:["meyer","skvortsov"]}, |
|
694 |
+ 4:{j:"meyer", txt:"Calgary n'a pas d'espoir attaquant vedette de calibre no 1 — c'est la lacune assumée de son pool. Meyer, relancé aux Remparts de Québec, a le profil de centre offensif que Parekh et Carels attendent devant eux. Button le voyait 2e.", b:["skvortsov","sundstrom"]}, |
|
695 |
+ 5:{j:"skvortsov", txt:"Choix de Toronto — SANS protection depuis que les Leafs ont gagné la loterie 2026 (la victoire McKenna a levé la protection top-10, rapporté par PuckPedia). Philadelphie cherche un attaquant élite : Skvortsov est le meilleur pur talent offensif disponible, consensus 4e-6e stable — et contrairement à Privalov, sans contrat KHL long terme.", b:["sundstrom","england"]}, |
|
696 |
+ 6:{j:"england", txt:"Seattle prend le joueur le plus en vogue du moment : England, « meilleur patineur de la cuvée » (Wheeler), vient de marquer 2 buts dans la finale du Hlinka-Gretzky — son consensus ajusté (5,8) le place devant Sundström. Sa vitesse d'élite complète les centres cérébraux Catton et O'Brien.", b:["sundstrom","nelson"]}, |
|
697 |
+ 7:{j:"sundstrom", txt:"Winnipeg a vu plusieurs de ses premiers choix plafonner : Sundström, meilleur Suédois de la cuvée et désigné meilleur joueur de son équipe au Hlinka, offre le plancher bidirectionnel le plus fiable encore disponible.", b:["nelson","zhilkin"]}, |
|
698 |
+ 8:{j:"nelson", txt:"Choix de la Floride (via l'échange Jones/Knight, sans protection). Chicago repêche deux fois dans le top-8 et double au centre : Nelson, déjà en NCAA à Notre Dame, est l'espoir le plus mature de la cuvée — parfait pour une reconstruction qui veut accélérer.", b:["zhilkin","jacobson"]}, |
|
699 |
+ 9:{j:"zhilkin", txt:"San Jose a une banque pleine de défenseurs et un besoin d'ailiers marqueurs : Zhilkin, 36 buts et capitaine à Saginaw, coche la case finition ET la case caractère (100 PIM).", b:["jacobson","pustovoy"]}, |
|
700 |
+ 10:{j:"jacobson", txt:"Nashville a le pool le plus profond mais aucune vedette : Jacobson, meneur de la production CHL de la cuvée (85 pts), est le pari talent-pur qui manque. Le gabarit inquiète — pas à ce prix.", b:["neuenschwander","yakunin"]}, |
|
701 |
+ 11:{j:"neuenschwander", txt:"St. Louis n'a « pas d'espoir véritablement élite » (Wheeler) : Neuenschwander, grand centre déjà pro en Suisse, offre le plancher le plus sûr du milieu de ronde avec un plafond de top-6.", b:["yakunin","cripps"]}, |
|
702 |
+ 12:{j:"yakunin", txt:"Le New Jersey n'a aucun top espoir à l'attaque. Yakunin (record MHL d'assistances U17) est un grand centre passeur ; son contrat KHL jusqu'en 2031 est le risque que les Devils, bien nantis en défense et devant le filet, peuvent absorber.", b:["cripps","pustovoy"]}, |
|
703 |
+ 13:{j:"cripps", txt:"Les Islanders ont regarni l'attaque en 2025 ; derrière la graduation de Schaefer, un D droitier mobile comme Cripps (9e chez THN) rééquilibre la banque. Or au Mondial U17 avec 26 minutes par match.", b:["shtyrkhunov","tait"]}, |
|
704 |
+ 14:{j:"pustovoy", txt:"Columbus a des espoirs en défense et devant le filet (Smith, Andreyanov), moins à l'aile : Pustovoy, joueur U18 le plus productif de la MHL (62 pts, 32 buts), est le meilleur marqueur disponible.", b:["kazda","davidson"]}, |
|
705 |
+ 15:{j:"kazda", txt:"Détroit cherche un « game-breaker » offensif : Kazda (1re équipe des recrues USHL, 12 pts en 12 matchs internationaux avec la Slovaquie) apporte finition et robustesse. Daily Faceoff le voit 11e.", b:["santala","tomek"]}, |
|
706 |
+ 16:{j:"santala", txt:"Washington n'a aucun espoir légitime au centre — la lacune la plus nette de sa banque. Santala, meilleur Finlandais de la cuvée, arrive à London (OHL) : le fit besoin-joueur le plus évident de toute la ronde.", b:["tomek","fitzhenry"]}, |
|
707 |
+ 17:{j:"tomek", txt:"Los Angeles a un trou béant au centre. Tomek marque déjà chez les pros tchèques (13 buts en Extraliga à 17 ans) — Daily Faceoff le classe 8e ; à 17, le risque de la fourchette (8e-23e) vaut la peine pour combler LE besoin.", b:["fitzhenry","meijer"]}, |
|
708 |
+ 18:{j:"fitzhenry", txt:"Anaheim manque de profondeur d'élite derrière McQueen. Fitzhenry (45 pts au NTDP U17, en route vers North Dakota) redonne un centre de talent au pipeline.", b:["meijer","edgar"]}, |
|
709 |
+ 19:{j:"meijer", txt:"L'Utah privilégie la qualité mais manque de quantité : Meijer, 4e marqueur de la Suède championne U18 comme sous-classé et déjà passé par la SHL, ajoute un centre fiable au pool.", b:["davidson","gordoncarroll"]}, |
|
710 |
+ 20:{j:"shtyrkhunov", txt:"Choix d'Edmonton (conditionnel : hors top-12, il appartient à Chicago). CHI, déjà servi aux 2e et 8e rangs, peut prendre le risque long terme : Shtyrkhunov, D droitier au dossier historique en MHL, est le genre de pari qu'une banque riche s'offre.", b:["gutierrez","tait"]}, |
|
711 |
+ 21:{j:"davidson", txt:"Philadelphie (son propre choix) n'a pas de vedette au centre ni de gros gabarit dominant : Davidson, 30 buts et 216 lb en saison recrue WHL, répond aux deux manques d'un seul choix.", b:["gutierrez","glance"]}, |
|
712 |
+ 22:{j:"gutierrez", txt:"Pittsburgh a transformé sa banque à l'attaque mais cherche un espoir premium à la ligne bleue : Gutierrez, meilleur D des 2009 du NTDP, en route vers Notre Dame.", b:["harper","tait"]}, |
|
713 |
+ 23:{j:"harper", txt:"Boston a regarni l'attaque (Hagens) mais sa défense d'avenir est mince : Harper, 57 points comme D recrue dans l'OHL, est la meilleure valeur offensive disponible à la ligne bleue.", b:["tait","eshkawkogan"]}, |
|
714 |
+ 24:{j:"tait", txt:"Le pool du Minnesota s'est vidé (chute de 21 rangs chez Wheeler) : il faut du volume et des positions premium. Tait, rare D gaucher de la cuvée avec 21 minutes par match, répond au besoin structurel.", b:["eshkawkogan","edgar"]}, |
|
715 |
+ 25:{j:"calce", txt:"Choix de Tampa Bay (protégé top-10 — ici 25e, il est transféré à Seattle). SEA, banque déjà profonde, peut avaler la variance : Calce (6e chez THN, 45e chez Tankathon ⚡) est le billet de loterie au meilleur ratio risque-rendement de la ronde.", b:["glance","hartl"]}, |
|
716 |
+ 26:{j:"glance", txt:"Dallas a la banque la plus mince de la ligue à égalité : n'importe quel talent réel est un gain. Glance, 56 points avec le NTDP U18, est la production la plus sûre encore au tableau.", b:["gordoncarroll","edgar"]}, |
|
717 |
+ 27:{j:"gordoncarroll", txt:"Buffalo n'a « aucun véritable espoir ailier » (Wheeler) : Gordon-Carroll, presque un point par match à Medicine Hat avant sa blessure, comble précisément cette case.", b:["edgar","wycisk"]}, |
|
718 |
+ 28:{j:"edgar", txt:"Montréal a un espoir A- à chaque position mais rien d'élite depuis la graduation de Demidov : Edgar, l'un des plus jeunes de la cuvée (né fin juillet 2009) avec 49 pts recrue dans l'OHL, est le pari croissance du CH.", b:["hartl","wycisk"]}, |
|
719 |
+ 29:{j:"eshkawkogan", txt:"Choix du Colorado (protégé top-10 — ici 29e, il va à Toronto via l'échange Nicolas Roy). Derrière McKenna et Cowan, la banque des Leafs projette mal : Eshkawkogan, D droitier de 53 points dans l'OHL, relève le plancher.", b:["hartl","johnsson"]}, |
|
720 |
+ 30:{j:"eklundaspe", txt:"Choix de Vegas (protégé top-10 — ici 30e, il va au New Jersey via Calgary, échange Nemec). NJD n'a aucun top espoir offensif : Eklund Aspe, 6'4\" et 29 pts en 19 matchs U18, est le pari de gabarit offensif suédois.", b:["hartl","naudins"]}, |
|
721 |
+ 31:{j:"hartl", txt:"La Caroline excelle avec les Européens des rondes tardives : Hartl, 21 buts au U20 tchèque et présent au Hlinka, prolonge la filière qui a produit ses meilleures aubaines.", b:["wycisk","scantlebury"]}, |
|
722 |
+ 32:{j:"wycisk", txt:"Ottawa manque de potentiel offensif dans son pool : Wycisk sort d'un Hlinka en or (4 pts en demi-finale, but en finale) — le « riser » le plus frais du tournoi terminé la veille de ces données.", b:["scantlebury","naudins"]}, |
|
723 |
+}; |
|
724 |
+ |
|
725 |
+/* Sleepers (écart production/rang ou momentum) et chutes (sourcées). */ |
|
726 |
+const SLEEPERS = ["scantlebury","harper","naudins","yermolov","kolmakov"]; |
|
727 |
+const CHUTES = [ |
|
728 |
+ {id:"murata", raison:"4e de l'aperçu TSN/Button en novembre 2025 → 41e chez Tankathon à l'été 2026 après une saison de 18 points en 59 matchs à Flint (sources : TSN 2025-11-07; Tankathon 2026-07)."}, |
|
729 |
+ {id:"privalov", raison:"Contrat de 4 ans signé avec le CSKA Moscou le liant à la KHL jusqu'au 1er juin 2030 — le facteur « disponibilité » évoqué par plusieurs sources comme frein à son rang réel (Complete Hockey News / S. Ellis, juin-juillet 2026)."}, |
|
730 |
+ {id:"meyer", raison:"Libéré du programme national américain le 14 juillet 2026 (rapporté par Jeff Marek) ; trajectoire redirigée vers les Remparts de Québec — de 2e chez Button (nov. 2025) à 4e-6e sur les listes d'été (Daily Faceoff, 2026-07-14)."}, |
|
731 |
+]; |
|
732 |
+ |
|
733 |
+/* ============================================================ |
|
734 |
+ ORDRE DU REPÊCHAGE ET LOTERIE |
|
735 |
+ ============================================================ */ |
|
736 |
+function construireOrdre(seq16){ // seq16 = ordre des 16 équipes hors séries |
|
737 |
+ return seq16.concat(ORDRE_SERIES).map((equipe,i)=>{ |
|
738 |
+ const rang = i+1; |
|
739 |
+ const ech = PICKS_ECHANGES[equipe]; |
|
740 |
+ let detenteur = equipe, noteCondition = null; |
|
741 |
+ if (ech) { const r = ech.resoudre(rang); detenteur = r.detenteur; noteCondition = r.note || null; } |
|
742 |
+ return {rang, equipeOriginale:equipe, detenteurActuel:detenteur, noteCondition, |
|
743 |
+ condition: ech ? ech.condition : null, transaction: ech ? ech.transaction : null, sourceEch: ech ? ech.source : null, |
|
744 |
+ joueurProjete: ORDRE_EDITORIAL[i] || null}; |
|
745 |
+ }); |
|
746 |
+} |
|
747 |
+/* Deux tirages pondérés sur cotes NOMINALES avec règle des 10 rangs : |
|
748 |
+ pour le choix n, seules les équipes au rang ≤ n+10 sont admissibles ; |
|
749 |
+ les points des inadmissibles sont transférés à la pire équipe admissible |
|
750 |
+ (mécanique du 1er tirage confirmée par Sportsnet ; appliquée par symétrie |
|
751 |
+ au 2e tirage, dont la LNH recalcule les cotes en direct — approximation |
|
752 |
+ documentée). */ |
|
753 |
+function tirageLoterie(){ |
|
754 |
+ const equipes = ORDRE_HORS_SERIES.map((eq,i)=>({eq, rang:i+1, cote:COTES_NOMINALES[i]})); |
|
755 |
+ const tirer = (pool, pick)=>{ |
|
756 |
+ const eligibles = pool.filter(x=>x.rang - pick <= 10); // remontée max 10 rangs |
|
757 |
+ const bonus = pool.filter(x=>x.rang - pick > 10).reduce((a,x)=>a+x.cote,0); |
|
758 |
+ const total = pool.reduce((a,x)=>a+x.cote,0); |
|
759 |
+ let r = Math.random()*total; |
|
760 |
+ for (const x of eligibles){ |
|
761 |
+ const c = x===eligibles[0] ? x.cote + bonus : x.cote; // transfert à la pire admissible |
|
762 |
+ r -= c; if (r<=0) return x; |
|
763 |
+ } |
|
764 |
+ return eligibles[eligibles.length-1]; |
|
765 |
+ }; |
|
766 |
+ const g1 = tirer(equipes, 1); |
|
767 |
+ const g2 = tirer(equipes.filter(x=>x!==g1), 2); |
|
768 |
+ const reste = ORDRE_HORS_SERIES.filter(eq=>eq!==g1.eq && eq!==g2.eq); |
|
769 |
+ return {gagnant1:g1.eq, gagnant2:g2.eq, ordre:[g1.eq, g2.eq, ...reste]}; |
|
770 |
+} |
|
771 |
+ |
|
772 |
+/* ============================================================ |
|
773 |
+ COMPOSANTS UTILITAIRES |
|
774 |
+ ============================================================ */ |
|
775 |
+const fmtRang = r => r==null ? "n.d." : (Math.round(r*10)/10).toFixed(1).replace(".", ","); |
|
776 |
+const nd = v => (v===null||v===undefined||v==="n.d.") ? "n.d." : v; |
|
777 |
+const ageAu = (naiss, ref="2027-06-30") => { |
|
778 |
+ if(!naiss || naiss==="n.d." || naiss.length<10) return null; |
|
779 |
+ const n=new Date(naiss), r=new Date(ref); |
|
780 |
+ let a=r.getFullYear()-n.getFullYear(); |
|
781 |
+ if(r.getMonth()<n.getMonth()||(r.getMonth()===n.getMonth()&&r.getDate()<n.getDate())) a--; |
|
782 |
+ return a; |
|
783 |
+}; |
|
784 |
+const TENDANCE = {up:{sym:"↑", coul:"var(--vert)", lib:"En hausse"}, down:{sym:"↓", coul:"var(--rouge)", lib:"En baisse"}, stable:{sym:"→", coul:"var(--texte2)", lib:"Stable"}}; |
|
785 |
+ |
|
786 |
+/* Vrais logos SVG des équipes (CDN officiel assets.nhle.com, variante fond |
|
787 |
+ sombre) — demande explicite de l'utilisateur. Repli : écusson stylisé |
|
788 |
+ (abréviation + couleurs) si le logo ne charge pas. */ |
|
789 |
+function Ecusson({abbr, taille=38}){ |
|
790 |
+ const eq = EQUIPES[abbr]; |
|
791 |
+ const [erreur, setErreur] = useState(false); |
|
792 |
+ if(!erreur) return <img src={`https://assets.nhle.com/logos/nhl/svg/${abbr}_dark.svg`} |
|
793 |
+ alt={`Logo — ${eq.nom}`} title={eq.nom} width={taille} height={taille} loading="lazy" |
|
794 |
+ onError={()=>setErreur(true)} style={{flexShrink:0, display:"block", objectFit:"contain"}}/>; |
|
795 |
+ return <div role="img" aria-label={eq.nom} title={eq.nom} style={{width:taille, height:taille, borderRadius:8, flexShrink:0, |
|
796 |
+ background:`linear-gradient(135deg, ${eq.c1} 55%, ${eq.c2})`, display:"flex", alignItems:"center", justifyContent:"center", |
|
797 |
+ fontFamily:"'Barlow Condensed'", fontWeight:700, fontSize:taille*0.36, color:"#fff", textShadow:"0 1px 3px rgba(0,0,0,.6)", border:"1px solid rgba(255,255,255,.15)"}}> |
|
798 |
+ {abbr} |
|
799 |
+ </div>; |
|
800 |
+} |
|
801 |
+function Avatar({esp, taille=64}){ |
|
802 |
+ const coul = COULEURS_LIGUE[esp.ligue] || "#4FC3F7"; |
|
803 |
+ const initiales = esp.nom.split(" ").map(m=>m[0]).slice(0,2).join(""); |
|
804 |
+ return <div role="img" aria-label={`Avatar de ${esp.nom} (initiales)`} style={{width:taille, height:taille, borderRadius:"50%", flexShrink:0, |
|
805 |
+ background:`linear-gradient(135deg, ${coul}33, ${coul}99)`, border:`2px solid ${coul}`, display:"flex", alignItems:"center", justifyContent:"center", |
|
806 |
+ fontFamily:"'Barlow Condensed'", fontWeight:700, fontSize:taille*0.34, color:"#fff"}}>{initiales}</div>; |
|
807 |
+} |
|
808 |
+function BadgeTendance({t}){ |
|
809 |
+ const d = TENDANCE[t] || TENDANCE.stable; |
|
810 |
+ return <span aria-label={`Tendance : ${d.lib}`} title={`Tendance : ${d.lib}`} style={{color:d.coul, fontWeight:700, fontSize:13}}>{d.sym} <span style={{fontSize:10, fontWeight:500}}>{d.lib}</span></span>; |
|
811 |
+} |
|
812 |
+function BadgeVolatil({esp}){ |
|
813 |
+ if(esp.volatil) return <span title={`Volatil : écart-type de ${fmtRang(esp.ecartType)} rangs entre les sources (fourchette ${esp.fourchette[0]}e-${esp.fourchette[1]}e)`} |
|
814 |
+ style={{color:"var(--ambre)", fontSize:11, fontWeight:600, border:"1px solid var(--ambre)", borderRadius:4, padding:"0 4px"}}>⚡ volatil</span>; |
|
815 |
+ if(esp.sourceUnique) return <span title="Classé par une seule source — incertitude élevée" |
|
816 |
+ style={{color:"var(--texte3)", fontSize:11, border:"1px solid var(--bordure)", borderRadius:4, padding:"0 4px"}}>source unique</span>; |
|
817 |
+ return null; |
|
818 |
+} |
|
819 |
+function InfoBulle({texte, children}){ |
|
820 |
+ return <span tabIndex={0} title={texte} style={{borderBottom:"1px dotted var(--texte3)", cursor:"help"}}>{children}</span>; |
|
821 |
+} |
|
822 |
+function LigneStats({esp, compact}){ |
|
823 |
+ const s = esp.stats; |
|
824 |
+ if(esp.position==="G") return <span className="num" style={{color:"var(--texte2)", fontSize:compact?12:13}}> |
|
825 |
+ {nd(s.mj)} MJ · MOY {s.moy==null?"n.d.":s.moy.toFixed(2)} · %Arr {s.arr==null?"n.d.":("."+Math.round(s.arr*1000))}</span>; |
|
826 |
+ if(s.pts==null) return <span style={{color:"var(--texte3)", fontSize:compact?12:13}}>stats 2025-26 : n.d.</span>; |
|
827 |
+ return <span className="num" style={{color:"var(--texte2)", fontSize:compact?12:13}}> |
|
828 |
+ {s.mj} MJ · {s.b} B · {s.p} P · <b style={{color:"var(--texte)"}}>{s.pts} PTS</b>{s.plusMoins!=null && <> · {s.plusMoins>0?"+":""}{s.plusMoins}</>} |
|
829 |
+ <span style={{color:"var(--texte3)"}}> ({esp.statsLigue}, 2025-26)</span></span>; |
|
830 |
+} |
|
831 |
+ |
|
832 |
+/* Radar SVG 5 axes, échelle 20-80 (une seule série → couleur accent). */ |
|
833 |
+function Radar({radar, taille=232}){ |
|
834 |
+ if(!radar) return <div style={{color:"var(--texte3)", fontSize:12, padding:"16px 0"}}>Évaluation détaillée n.d. — données publiques insuffisantes.</div>; |
|
835 |
+ const axes=[["patinage","Patinage"],["sensJeu","Sens du jeu"],["tir","Tir"],["competitivite","Compétitivité"],["jeuDefensif","Jeu défensif"]]; |
|
836 |
+ const c=taille/2, R=c-34; |
|
837 |
+ const pt=(i,val)=>{ const a=-Math.PI/2 + i*2*Math.PI/5; const r=R*(val-20)/60; return [c+r*Math.cos(a), c+r*Math.sin(a)]; }; |
|
838 |
+ const poly=axes.map(([k],i)=>pt(i,radar[k]).join(",")).join(" "); |
|
839 |
+ return <figure style={{margin:0}}> |
|
840 |
+ <svg width={taille} height={taille} role="img" aria-label={"Graphique radar : " + axes.map(([k,l])=>`${l} ${radar[k]}`).join(", ") + " (échelle 20-80)"}> |
|
841 |
+ {[35,50,65,80].map(v=><polygon key={v} points={axes.map(([k],i)=>pt(i,v).join(",")).join(" ")} fill="none" stroke="var(--bordure)" strokeWidth="1"/>)} |
|
842 |
+ {axes.map(([k,l],i)=>{ const [x,y]=pt(i,80); return <line key={k} x1={c} y1={c} x2={x} y2={y} stroke="var(--bordure)"/>; })} |
|
843 |
+ <polygon points={poly} fill="rgba(79,195,247,.22)" stroke="var(--glace)" strokeWidth="2"/> |
|
844 |
+ {axes.map(([k],i)=>{ const [x,y]=pt(i,radar[k]); return <circle key={k} cx={x} cy={y} r="3.5" fill="var(--glace)"/>; })} |
|
845 |
+ {axes.map(([k,l],i)=>{ const [x,y]=pt(i,93); const xc=Math.max(56, Math.min(taille-56, x)); return <text key={k} x={xc} y={y} textAnchor="middle" dominantBaseline="middle" fill="var(--texte2)" fontSize="11">{l} <tspan fill="var(--glace)" fontWeight="700">{radar[k]}</tspan></text>; })} |
|
846 |
+ </svg> |
|
847 |
+ <figcaption style={{fontSize:10, color:"var(--texte3)", maxWidth:taille}}>Échelle 20-80 (style recrutement) — synthèse éditoriale des rapports publics, pas des notes officielles.</figcaption> |
|
848 |
+ </figure>; |
|
849 |
+} |
|
850 |
+ |
|
851 |
+function TableRangs({esp}){ |
|
852 |
+ const lignes = SOURCES.map(s=>{ |
|
853 |
+ let val = esp.rangsParSource[s.cle]; |
|
854 |
+ if(!Number.isFinite(val)){ |
|
855 |
+ if(s.cle==="wheeler" && esp.mentionWheeler) val = "Mention honorable"; |
|
856 |
+ else if(s.cle==="dfo" && esp.mentionDfo) val = "« Also considered »"; |
|
857 |
+ else val = "n.c."; |
|
858 |
+ } else val = val + "e"; |
|
859 |
+ return {...s, val}; |
|
860 |
+ }); |
|
861 |
+ return <table style={{width:"100%", borderCollapse:"collapse", fontSize:12}}> |
|
862 |
+ <caption style={{textAlign:"left", fontSize:11, color:"var(--texte3)", paddingBottom:4}}>Rangs par source (n.c. = non classé par cette source)</caption> |
|
863 |
+ <thead><tr>{["Source","Date","Rang"].map(h=><th key={h} style={{textAlign:"left", color:"var(--texte3)", fontWeight:600, padding:"3px 6px", borderBottom:"1px solid var(--bordure)"}}>{h}</th>)}</tr></thead> |
|
864 |
+ <tbody>{lignes.map(l=><tr key={l.cle}> |
|
865 |
+ <td style={{padding:"3px 6px", color:"var(--texte2)"}}>{l.nom} <span style={{color:"var(--texte3)"}}>({l.poids} %)</span></td> |
|
866 |
+ <td style={{padding:"3px 6px", color:"var(--texte3)"}} className="num">{l.date}</td> |
|
867 |
+ <td style={{padding:"3px 6px", fontWeight:600}} className="num">{l.val}</td></tr>)} |
|
868 |
+ </tbody></table>; |
|
869 |
+} |
|
870 |
+ |
|
871 |
+/* ============================================================ |
|
872 |
+ FICHE JOUEUR (panneau latéral) |
|
873 |
+ ============================================================ */ |
|
874 |
+function Fiche({esp, onFermer, choix}){ |
|
875 |
+ if(!esp) return null; |
|
876 |
+ const age = ageAu(esp.naissance); |
|
877 |
+ return <aside className="apparait" aria-label={`Fiche de ${esp.nom}`} style={{background:"var(--panneau)", border:"1px solid var(--bordure)", borderRadius:12, padding:18, position:"sticky", top:12, maxHeight:"calc(100vh - 24px)", overflowY:"auto"}}> |
|
878 |
+ <div style={{display:"flex", justifyContent:"space-between", alignItems:"flex-start", gap:10}}> |
|
879 |
+ <div style={{display:"flex", gap:12, alignItems:"center"}}> |
|
880 |
+ <Avatar esp={esp} taille={62}/> |
|
881 |
+ <div> |
|
882 |
+ <h2 style={{fontSize:24, lineHeight:1.1}}>{esp.nom} <span aria-hidden="true">{DRAPEAUX[esp.nationalite]||"🏳️"}</span></h2> |
|
883 |
+ <div style={{color:"var(--texte2)", fontSize:12}}> |
|
884 |
+ {esp.position} · tir {nd(esp.tir)} · <InfoBulle texte={esp.tailleCm ? `${esp.tailleCm} cm` : "taille métrique n.d."}>{nd(esp.taille)}</InfoBulle> · {esp.poids ? esp.poids+" lb" : "poids n.d."} · {age!=null ? `${age} ans au repêchage` : "naissance n.d."} |
|
885 |
+ </div> |
|
886 |
+ <div style={{color:"var(--texte2)", fontSize:12}}>{esp.equipeActuelle} · {esp.ligue} · nationalité : {nd(esp.nationalite)}</div> |
|
887 |
+ </div> |
|
888 |
+ </div> |
|
889 |
+ <button onClick={onFermer} aria-label="Fermer la fiche" style={{background:"none", border:"1px solid var(--bordure)", color:"var(--texte2)", borderRadius:6, width:28, height:28}}>✕</button> |
|
890 |
+ </div> |
|
891 |
+ <div style={{display:"flex", gap:10, flexWrap:"wrap", margin:"10px 0", alignItems:"center"}}> |
|
892 |
+ <span style={{background:"var(--panneau2)", border:"1px solid var(--bordure)", borderRadius:6, padding:"2px 8px", fontSize:12}} className="num"> |
|
893 |
+ Consensus : <b style={{color:"var(--glace)"}}>{fmtRang(esp.rangConsensus)}</b>{esp.hlinka && <span style={{color:"var(--texte3)"}}> (brut {fmtRang(esp.rangConsensusBrut)} {esp.hlinka.aj<0?"−":"+"}{Math.abs(esp.hlinka.aj).toFixed(1).replace(".",",")} Hlinka)</span>}{esp.fourchette && esp.fourchette[0]!==esp.fourchette[1] && <span style={{color:"var(--texte3)"}}> (classé entre {esp.fourchette[0]}e et {esp.fourchette[1]}e selon les sources)</span>} |
|
894 |
+ </span> |
|
895 |
+ {esp.hlinka && <span title={esp.hlinka.source} style={{background:"rgba(34,197,94,.10)", border:"1px solid var(--vert)", borderRadius:6, padding:"2px 8px", fontSize:11, color:"var(--vert)"}}>🏆 Hlinka 2026</span>} |
|
896 |
+ <BadgeTendance t={esp.tendance}/> <BadgeVolatil esp={esp}/> |
|
897 |
+ <span style={{fontSize:12, color: esp.risque==="élevé"?"var(--rouge)":esp.risque==="moyen"?"var(--ambre)":"var(--vert)"}}>Risque : {esp.risque}</span> |
|
898 |
+ </div> |
|
899 |
+ <LigneStats esp={esp}/> |
|
900 |
+ <div style={{display:"flex", justifyContent:"center", margin:"8px 0"}}><Radar radar={esp.radar}/></div> |
|
901 |
+ <TableRangs esp={esp}/> |
|
902 |
+ {esp.hlinka && <div style={{margin:"6px 0", background:"rgba(34,197,94,.08)", border:"1px solid rgba(34,197,94,.35)", borderRadius:8, padding:"6px 10px", fontSize:12}}> |
|
903 |
+ <b style={{color:"var(--vert)"}}>🏆 Coupe Hlinka-Gretzky 2026 (terminée le 8 août) :</b> <span style={{color:"var(--texte2)"}}>{esp.hlinka.fait}.</span> |
|
904 |
+ <span className="num" style={{color:"var(--texte2)"}}> Ajustement du consensus : <b>{esp.hlinka.aj<0?"−":"+"}{Math.abs(esp.hlinka.aj).toFixed(1).replace(".",",")} rang</b> ({fmtRang(esp.rangConsensusBrut)} → {fmtRang(esp.rangConsensus)}).</span> |
|
905 |
+ <span style={{color:"var(--texte3)"}}> Source : {esp.hlinka.source}.</span> |
|
906 |
+ </div>} |
|
907 |
+ <div style={{fontSize:10, color:"var(--texte3)", margin:"4px 0 10px"}}>Historique du consensus : n.d. — premier instantané (août 2026), aucune évolution à tracer encore.</div> |
|
908 |
+ <h3 style={{color:"var(--vert)", fontSize:15, marginTop:8}}>Forces</h3> |
|
909 |
+ <ul style={{paddingLeft:18, fontSize:13, color:"var(--texte2)"}}>{esp.forces.map((f,i)=><li key={i}>{f}</li>)}</ul> |
|
910 |
+ <h3 style={{color:"var(--rouge)", fontSize:15, marginTop:8}}>Points à améliorer</h3> |
|
911 |
+ <ul style={{paddingLeft:18, fontSize:13, color:"var(--texte2)"}}>{esp.faiblesses.map((f,i)=><li key={i}>{f}</li>)}</ul> |
|
912 |
+ <div style={{marginTop:8, fontSize:13}}><b>Comparable (style) :</b> <span style={{color:"var(--texte2)"}}>{esp.comparableLNH}</span></div> |
|
913 |
+ <div style={{fontSize:13}}><b>Plafond projeté :</b> <span style={{color:"var(--texte2)"}}>{esp.projectionPlafond}</span></div> |
|
914 |
+ {choix && <div style={{marginTop:10, background:"var(--panneau2)", border:"1px solid var(--bordure)", borderRadius:8, padding:10, fontSize:13}}> |
|
915 |
+ <b style={{color:"var(--glace)"}}>Logique du choix no {choix.rang} ({EQUIPES[choix.detenteurActuel].nom}) :</b> |
|
916 |
+ <p style={{color:"var(--texte2)", marginTop:4}}>{choix.logique}</p> |
|
917 |
+ {choix.autresOptions && <p style={{color:"var(--texte3)", fontSize:12, marginTop:6}}>Plans B plausibles : {choix.autresOptions.map(id=>parId[id].nom).join(" · ")}</p>} |
|
918 |
+ </div>} |
|
919 |
+ <p style={{marginTop:10, fontSize:13, color:"var(--texte2)", borderLeft:"3px solid var(--glace)", paddingLeft:10}}>{esp.analyse}</p> |
|
920 |
+ </aside>; |
|
921 |
+} |
|
922 |
+ |
|
923 |
+/* ============================================================ |
|
924 |
+ TABLEAU DU MOCK DRAFT |
|
925 |
+ ============================================================ */ |
|
926 |
+function RangeeChoix({choix, esp, selection, onSelection, apresLoterie}){ |
|
927 |
+ const eq = EQUIPES[choix.detenteurActuel]; |
|
928 |
+ const via = choix.detenteurActuel !== choix.equipeOriginale; |
|
929 |
+ return <div role="button" tabIndex={0} onClick={onSelection} onKeyDown={e=>{if(e.key==="Enter"||e.key===" "){e.preventDefault();onSelection();}}} |
|
930 |
+ aria-label={`Choix ${choix.rang}, ${eq.nom}${via?` via ${EQUIPES[choix.equipeOriginale].nom}`:""} : ${esp?esp.nom:"aucun joueur"}`} |
|
931 |
+ className="apparait" |
|
932 |
+ style={{display:"flex", alignItems:"center", gap:10, padding:"8px 10px", borderRadius:10, cursor:"pointer", |
|
933 |
+ background:selection?"rgba(79,195,247,.10)":"var(--panneau)", border:`1px solid ${selection?"var(--glace)":"var(--bordure)"}`, marginBottom:6}}> |
|
934 |
+ <div className="num titre" style={{width:30, textAlign:"center", fontSize:20, fontWeight:700, color: choix.rang<=3?"var(--glace)":"var(--texte2)"}}>{choix.rang}</div> |
|
935 |
+ <Ecusson abbr={choix.detenteurActuel}/> |
|
936 |
+ <div style={{minWidth:86}}> |
|
937 |
+ <div style={{fontWeight:600, fontSize:13}}>{choix.detenteurActuel}</div> |
|
938 |
+ {via && <div style={{fontSize:10, color:"var(--ambre)"}}> |
|
939 |
+ <InfoBulle texte={`${choix.condition||""} ${choix.transaction||""} (source : ${choix.sourceEch||"n.d."})`}>via {choix.equipeOriginale}</InfoBulle> |
|
940 |
+ </div>} |
|
941 |
+ {choix.noteCondition && <div style={{fontSize:10, color:"var(--ambre)"}}><InfoBulle texte={choix.noteCondition}>⚠ condition</InfoBulle></div>} |
|
942 |
+ </div> |
|
943 |
+ {esp ? <> |
|
944 |
+ <div style={{flex:1, minWidth:0}}> |
|
945 |
+ <div style={{display:"flex", gap:6, alignItems:"center", flexWrap:"wrap"}}> |
|
946 |
+ <b style={{fontSize:14}}>{esp.nom}</b> |
|
947 |
+ <span aria-hidden="true">{DRAPEAUX[esp.nationalite]||"🏳️"}</span> |
|
948 |
+ <span style={{fontSize:11, color:"var(--texte2)", border:"1px solid var(--bordure)", borderRadius:4, padding:"0 4px"}}>{esp.position}</span> |
|
949 |
+ <span style={{fontSize:11, color:COULEURS_LIGUE[esp.ligue]||"var(--texte2)"}}>{esp.ligue}</span> |
|
950 |
+ <BadgeVolatil esp={esp}/> |
|
951 |
+ </div> |
|
952 |
+ <LigneStats esp={esp} compact/> |
|
953 |
+ </div> |
|
954 |
+ <BadgeTendance t={esp.tendance}/> |
|
955 |
+ </> : <div style={{flex:1, color:"var(--texte3)", fontSize:12}}>—</div>} |
|
956 |
+ </div>; |
|
957 |
+} |
|
958 |
+ |
|
959 |
+/* ============================================================ |
|
960 |
+ SIMULATEUR DE LOTERIE — révélation théâtrale du 16e au 1er |
|
961 |
+ ============================================================ */ |
|
962 |
+function PanneauLoterie({onResultat, onReinit, historique, noSim, ordreActuel}){ |
|
963 |
+ const [reveles, setReveles] = useState(null); // liste [{rang, equipe}] révélés progressivement |
|
964 |
+ const [enCours, setEnCours] = useState(false); |
|
965 |
+ const minuterie = useRef(null); |
|
966 |
+ useEffect(()=>()=>clearTimeout(minuterie.current),[]); |
|
967 |
+ const simuler = () => { |
|
968 |
+ if(enCours) return; |
|
969 |
+ const res = tirageLoterie(); |
|
970 |
+ setEnCours(true); setReveles([]); |
|
971 |
+ const seq = res.ordre.map((eq,i)=>({rang:i+1, equipe:eq})).reverse(); // 16 → 1 |
|
972 |
+ let i = 0; |
|
973 |
+ const etape = () => { |
|
974 |
+ i++; |
|
975 |
+ setReveles(seq.slice(0,i)); |
|
976 |
+ if(i<seq.length){ minuterie.current = setTimeout(etape, seq.length-i<=3 ? 900 : 220); } |
|
977 |
+ else { setEnCours(false); onResultat(res); } |
|
978 |
+ }; |
|
979 |
+ minuterie.current = setTimeout(etape, 300); |
|
980 |
+ }; |
|
981 |
+ return <section aria-label="Simulateur de loterie" style={{background:"var(--panneau)", border:"1px solid var(--bordure)", borderRadius:12, padding:16, marginBottom:14}}> |
|
982 |
+ <div style={{display:"flex", justifyContent:"space-between", flexWrap:"wrap", gap:8, alignItems:"center"}}> |
|
983 |
+ <h2 style={{fontSize:20}}>🎰 Simulateur de loterie <span style={{fontSize:12, color:"var(--texte3)", fontWeight:400}}>({LOTERIE_SOURCE})</span></h2> |
|
984 |
+ <div style={{display:"flex", gap:8}}> |
|
985 |
+ <button onClick={simuler} disabled={enCours} style={{background:"var(--glace)", color:"#04121F", border:"none", borderRadius:8, padding:"8px 14px", fontWeight:700, opacity:enCours?0.5:1}}> |
|
986 |
+ {enCours ? "Tirage en cours…" : "Simuler la loterie"}</button> |
|
987 |
+ <button onClick={()=>{setReveles(null); onReinit();}} style={{background:"none", color:"var(--texte2)", border:"1px solid var(--bordure)", borderRadius:8, padding:"8px 14px"}}>Réinitialiser à l'ordre de base</button> |
|
988 |
+ </div> |
|
989 |
+ </div> |
|
990 |
+ <p style={{fontSize:12, color:"var(--texte2)", margin:"6px 0"}}>Règles 2026 appliquées : 2 tirages, remontée maximale de 10 rangs (1er choix : rangs 1-11 admissibles, les 7,0 points des rangs 12-16 sont transférés à la pire équipe → {ORDRE_HORS_SERIES[0]} effectif 25,5 % ; 2e choix : rangs 1-12 admissibles). Cotes nominales officielles : {ORDRE_HORS_SERIES.map((eq,i)=>`${eq} ${COTES_NOMINALES[i].toFixed(1).replace(".",",")}`).join(" · ")} (%). Les cotes du 2e tirage sont recalculées après le 1er (approximation documentée).</p> |
|
991 |
+ {reveles && <div style={{display:"flex", flexWrap:"wrap", gap:6, marginTop:8}} aria-live="polite"> |
|
992 |
+ {reveles.map(r=><div key={r.rang} className="apparait" style={{display:"flex", alignItems:"center", gap:6, background:"var(--panneau2)", border:`1px solid ${r.rang<=2?"var(--glace)":"var(--bordure)"}`, borderRadius:8, padding:"4px 8px", animation: r.rang<=2 ? "apparait .25s ease both, pulse-glace 1.6s ease 2" : undefined}}> |
|
993 |
+ <span className="num titre" style={{fontSize:16, fontWeight:700, color:r.rang<=2?"var(--glace)":"var(--texte2)"}}>{r.rang}</span> |
|
994 |
+ <Ecusson abbr={r.equipe} taille={26}/><span style={{fontSize:12}}>{r.equipe}</span> |
|
995 |
+ </div>)} |
|
996 |
+ </div>} |
|
997 |
+ {noSim>0 && <div style={{fontSize:12, color:"var(--texte3)", marginTop:8}}> |
|
998 |
+ Simulation n° {noSim} · Historique : {historique.map((h,i)=><span key={i} className="num"> [{h.gagnant1} 1er, {h.gagnant2} 2e]</span>)} |
|
999 |
+ </div>} |
|
1000 |
+ </section>; |
|
1001 |
+} |
|
1002 |
+ |
|
1003 |
+/* ============================================================ |
|
1004 |
+ SLEEPERS ET CHUTES |
|
1005 |
+ ============================================================ */ |
|
1006 |
+function SectionSleepers({onVoir}){ |
|
1007 |
+ return <section aria-label="Sleepers et chutes" className="apparait" style={{background:"var(--panneau)", border:"1px solid var(--bordure)", borderRadius:12, padding:16, marginBottom:14}}> |
|
1008 |
+ <h2 style={{fontSize:20, marginBottom:8}}>💎 Sleepers <span style={{fontSize:12, color:"var(--texte3)", fontWeight:400}}>— écart production/rang ou momentum fort</span></h2> |
|
1009 |
+ <div style={{display:"grid", gridTemplateColumns:"repeat(auto-fill, minmax(240px, 1fr))", gap:8}}> |
|
1010 |
+ {SLEEPERS.map(id=>{const e=parId[id]; return <button key={id} onClick={()=>onVoir(id)} style={{textAlign:"left", background:"var(--panneau2)", border:"1px solid var(--bordure)", borderRadius:8, padding:10, color:"var(--texte)"}}> |
|
1011 |
+ <div style={{display:"flex", gap:8, alignItems:"center"}}><Avatar esp={e} taille={34}/><div><b style={{fontSize:13}}>{e.nom}</b><div style={{fontSize:11, color:"var(--texte2)"}}>{e.position} · {e.ligue} · consensus {fmtRang(e.rangConsensus)}</div></div></div> |
|
1012 |
+ <div style={{fontSize:11, color:"var(--texte2)", marginTop:6}}>{e.analyse.length>150 ? e.analyse.slice(0,150)+"…" : e.analyse}</div> |
|
1013 |
+ </button>;})} |
|
1014 |
+ </div> |
|
1015 |
+ <h2 style={{fontSize:20, margin:"14px 0 8px"}}>📉 En chute <span style={{fontSize:12, color:"var(--texte3)", fontWeight:400}}>— explications factuelles sourcées</span></h2> |
|
1016 |
+ <div style={{display:"grid", gridTemplateColumns:"repeat(auto-fill, minmax(280px, 1fr))", gap:8}}> |
|
1017 |
+ {CHUTES.map(c=>{const e=parId[c.id]; return <button key={c.id} onClick={()=>onVoir(c.id)} style={{textAlign:"left", background:"var(--panneau2)", border:"1px solid rgba(239,68,68,.35)", borderRadius:8, padding:10, color:"var(--texte)"}}> |
|
1018 |
+ <div style={{display:"flex", gap:8, alignItems:"center"}}><Avatar esp={e} taille={34}/><b style={{fontSize:13}}>{e.nom} <span style={{color:"var(--rouge)"}}>↓</span></b></div> |
|
1019 |
+ <div style={{fontSize:11, color:"var(--texte2)", marginTop:6}}>{c.raison}</div> |
|
1020 |
+ </button>;})} |
|
1021 |
+ </div> |
|
1022 |
+ </section>; |
|
1023 |
+} |
|
1024 |
+ |
|
1025 |
+/* ============================================================ |
|
1026 |
+ FILTRES / RECHERCHE / TRI |
|
1027 |
+ ============================================================ */ |
|
1028 |
+const OPTIONS_TRI = [ |
|
1029 |
+ {cle:"consensus", lib:"Rang consensus"}, {cle:"pts", lib:"Points"}, {cle:"ptsParMatch", lib:"Points/match"}, |
|
1030 |
+ {cle:"taille", lib:"Taille"}, {cle:"age", lib:"Âge"}, |
|
1031 |
+]; |
|
1032 |
+function filtrerEspoirs(liste, f){ |
|
1033 |
+ let r = liste; |
|
1034 |
+ if(f.recherche) r = r.filter(e=>e.nom.toLowerCase().includes(f.recherche.toLowerCase())); |
|
1035 |
+ if(f.position!=="Tous") r = r.filter(e=>e.position===f.position); |
|
1036 |
+ if(f.ligue!=="Toutes") r = r.filter(e=>e.ligue===f.ligue); |
|
1037 |
+ if(f.nationalite!=="Toutes") r = r.filter(e=>e.nationalite===f.nationalite); |
|
1038 |
+ if(f.risque!=="Tous") r = r.filter(e=>e.risque===f.risque); |
|
1039 |
+ if(f.tendance!=="Toutes") r = r.filter(e=>e.tendance===f.tendance); |
|
1040 |
+ const cmp = { |
|
1041 |
+ consensus:(a,b)=>(a.rangConsensus??999)-(b.rangConsensus??999), |
|
1042 |
+ pts:(a,b)=>(b.stats.pts??-1)-(a.stats.pts??-1), |
|
1043 |
+ ptsParMatch:(a,b)=>((b.stats.pts??0)/(b.stats.mj||1))-((a.stats.pts??0)/(a.stats.mj||1)), |
|
1044 |
+ taille:(a,b)=>(b.tailleCm??0)-(a.tailleCm??0), |
|
1045 |
+ age:(a,b)=>{const va=a.naissance&&a.naissance.length>=7?a.naissance:"9999"; const vb=b.naissance&&b.naissance.length>=7?b.naissance:"9999"; return va<vb?-1:va>vb?1:0;}, |
|
1046 |
+ }[f.tri] || ((a,b)=>0); |
|
1047 |
+ return [...r].sort(cmp); |
|
1048 |
+} |
|
1049 |
+function BarreFiltres({f, setF, liste}){ |
|
1050 |
+ const uniques = cle => ["Tous"==="Tous"?null:null, ...new Set(liste.map(e=>e[cle]))].filter(Boolean); |
|
1051 |
+ const sel = (label, cle, options, defaut) => <label style={{fontSize:11, color:"var(--texte2)", display:"flex", flexDirection:"column", gap:2}}>{label} |
|
1052 |
+ <select value={f[cle]} onChange={e=>setF({...f,[cle]:e.target.value})} style={{background:"var(--panneau2)", color:"var(--texte)", border:"1px solid var(--bordure)", borderRadius:6, padding:"5px 6px", fontSize:12}}> |
|
1053 |
+ <option>{defaut}</option>{options.map(o=><option key={o} value={o}>{o}</option>)} |
|
1054 |
+ </select></label>; |
|
1055 |
+ return <div style={{display:"flex", gap:8, flexWrap:"wrap", alignItems:"flex-end", marginBottom:10}}> |
|
1056 |
+ <label style={{fontSize:11, color:"var(--texte2)", display:"flex", flexDirection:"column", gap:2, flex:"1 1 160px"}}>Recherche |
|
1057 |
+ <input type="search" placeholder="Nom du joueur…" value={f.recherche} onChange={e=>setF({...f,recherche:e.target.value})} |
|
1058 |
+ style={{background:"var(--panneau2)", color:"var(--texte)", border:"1px solid var(--bordure)", borderRadius:6, padding:"5px 8px", fontSize:12}}/></label> |
|
1059 |
+ {sel("Position","position",[...new Set(liste.map(e=>e.position))],"Tous")} |
|
1060 |
+ {sel("Ligue","ligue",[...new Set(liste.map(e=>e.ligue))],"Toutes")} |
|
1061 |
+ {sel("Nationalité","nationalite",[...new Set(liste.map(e=>e.nationalite))],"Toutes")} |
|
1062 |
+ {sel("Risque","risque",["faible","moyen","élevé"],"Tous")} |
|
1063 |
+ {sel("Tendance","tendance",["up","down","stable"],"Toutes")} |
|
1064 |
+ <label style={{fontSize:11, color:"var(--texte2)", display:"flex", flexDirection:"column", gap:2}}>Tri |
|
1065 |
+ <select value={f.tri} onChange={e=>setF({...f,tri:e.target.value})} style={{background:"var(--panneau2)", color:"var(--texte)", border:"1px solid var(--bordure)", borderRadius:6, padding:"5px 6px", fontSize:12}}> |
|
1066 |
+ {OPTIONS_TRI.map(o=><option key={o.cle} value={o.cle}>{o.lib}</option>)} |
|
1067 |
+ </select></label> |
|
1068 |
+ </div>; |
|
1069 |
+} |
|
1070 |
+ |
|
1071 |
+/* ============================================================ |
|
1072 |
+ API CLAUDE (Claudeception) — clé gérée par l'environnement, |
|
1073 |
+ jamais dans le code. Blocs traités par TYPE, jamais par position. |
|
1074 |
+ ============================================================ */ |
|
1075 |
+async function appelClaude(messages, avecRecherche=false, maxTokens=1000){ |
|
1076 |
+ const corps = {model:"claude-sonnet-4-6", max_tokens:maxTokens, messages}; |
|
1077 |
+ if(avecRecherche) corps.tools = [{type:"web_search_20250305", name:"web_search"}]; |
|
1078 |
+ const rep = await fetch("https://api.anthropic.com/v1/messages", { |
|
1079 |
+ method:"POST", headers:{"Content-Type":"application/json"}, body:JSON.stringify(corps) |
|
1080 |
+ }); |
|
1081 |
+ if(!rep.ok) throw new Error(`L'API a répondu ${rep.status}`); |
|
1082 |
+ const data = await rep.json(); |
|
1083 |
+ return data.content.filter(b=>b.type==="text").map(b=>b.text).join("\n"); |
|
1084 |
+} |
|
1085 |
+function nettoyerJSON(txt){ |
|
1086 |
+ let t = txt.trim(); |
|
1087 |
+ t = t.replace(/^```json\s*/i,"").replace(/^```\s*/,"").replace(/```\s*$/,""); |
|
1088 |
+ const debut = Math.min(...["[","{"].map(c=>{const i=t.indexOf(c); return i===-1?Infinity:i;})); |
|
1089 |
+ if(Number.isFinite(debut)) t = t.slice(debut); |
|
1090 |
+ return t.trim(); |
|
1091 |
+} |
|
1092 |
+function etatCompact(choix){ |
|
1093 |
+ return JSON.stringify({ |
|
1094 |
+ meta:{maj:META.dateDonnees, note:"ordre simulé (classement 2025-26), loterie 2027 non tenue"}, |
|
1095 |
+ mock: choix.map(c=>({rang:c.rang, equipe:c.detenteurActuel, via:c.equipeOriginale!==c.detenteurActuel?c.equipeOriginale:undefined, |
|
1096 |
+ joueur:c.joueurProjete?parId[c.joueurProjete].nom:null})), |
|
1097 |
+ espoirs: ESPOIRS.filter(e=>e.rangConsensus!=null).map(e=>({nom:e.nom, pos:e.position, ligue:e.ligue, consensus:Math.round((e.rangConsensus)*10)/10, pts:e.stats.pts, mj:e.stats.mj, tendance:e.tendance, risque:e.risque})) |
|
1098 |
+ }); |
|
1099 |
+} |
|
1100 |
+ |
|
1101 |
+/* ============================================================ |
|
1102 |
+ CHAT ANALYTIQUE (repliable, bas droite) |
|
1103 |
+ ============================================================ */ |
|
1104 |
+function Chat({choix}){ |
|
1105 |
+ const [ouvert, setOuvert] = useState(false); |
|
1106 |
+ const [messages, setMessages] = useState([]); // {role, content} — historique complet renvoyé à chaque tour |
|
1107 |
+ const [saisie, setSaisie] = useState(""); |
|
1108 |
+ const [charge, setCharge] = useState(false); |
|
1109 |
+ const [erreur, setErreur] = useState(null); |
|
1110 |
+ const bas = useRef(null); |
|
1111 |
+ useEffect(()=>{ bas.current && bas.current.scrollIntoView({behavior:"smooth"}); },[messages, charge]); |
|
1112 |
+ const envoyer = async () => { |
|
1113 |
+ const q = saisie.trim(); if(!q || charge) return; |
|
1114 |
+ setErreur(null); setSaisie(""); |
|
1115 |
+ const prompteSys = `Tu es un recruteur-chef de la LNH. Réponds en français, brièvement, en te basant sur les données suivantes : ${etatCompact(choix)}. Pour toute question sur des faits récents, utilise web_search. Ne jamais inventer de statistique — dis « n.d. » si tu ne sais pas.`; |
|
1116 |
+ const nouveaux = [...messages, {role:"user", content: messages.length===0 ? prompteSys+"\n\nQuestion : "+q : q}]; |
|
1117 |
+ setMessages([...messages, {role:"user", content:q, affiche:q}]); |
|
1118 |
+ setCharge(true); |
|
1119 |
+ try{ |
|
1120 |
+ const texte = await appelClaude(nouveaux.map(m=>({role:m.role, content:m.content})), true, 800); |
|
1121 |
+ setMessages(m=>[...m.slice(0,-1), {role:"user", content:nouveaux[nouveaux.length-1].content, affiche:q}, {role:"assistant", content:texte, affiche:texte}]); |
|
1122 |
+ }catch(e){ |
|
1123 |
+ setErreur("Échec de l'appel à l'assistant (" + e.message + "). Réessayez dans un instant — l'API n'est accessible que dans un environnement qui fournit la clé automatiquement."); |
|
1124 |
+ setMessages(m=>m.slice(0,-1)); |
|
1125 |
+ setSaisie(q); |
|
1126 |
+ }finally{ setCharge(false); } |
|
1127 |
+ }; |
|
1128 |
+ return <div style={{position:"fixed", right:14, bottom:14, zIndex:50, width: ouvert ? "min(380px, calc(100vw - 28px))" : "auto"}}> |
|
1129 |
+ {ouvert ? <div className="apparait" style={{background:"var(--panneau)", border:"1px solid var(--glace)", borderRadius:12, display:"flex", flexDirection:"column", height:"min(480px, 70vh)", boxShadow:"0 12px 40px rgba(0,0,0,.5)"}}> |
|
1130 |
+ <div style={{display:"flex", justifyContent:"space-between", alignItems:"center", padding:"10px 12px", borderBottom:"1px solid var(--bordure)"}}> |
|
1131 |
+ <b className="titre" style={{fontSize:16}}>💬 Recruteur-chef (IA)</b> |
|
1132 |
+ <button onClick={()=>setOuvert(false)} aria-label="Replier le chat" style={{background:"none", border:"none", color:"var(--texte2)", fontSize:16}}>▾</button> |
|
1133 |
+ </div> |
|
1134 |
+ <div style={{flex:1, overflowY:"auto", padding:12, display:"flex", flexDirection:"column", gap:8}} aria-live="polite"> |
|
1135 |
+ {messages.length===0 && <div style={{fontSize:12, color:"var(--texte3)"}}>Posez une question sur le mock draft, un espoir, une équipe… L'assistant s'appuie sur les données de la plateforme et peut chercher le web pour les faits récents.</div>} |
|
1136 |
+ {messages.map((m,i)=><div key={i} style={{alignSelf:m.role==="user"?"flex-end":"flex-start", maxWidth:"85%", background:m.role==="user"?"rgba(79,195,247,.15)":"var(--panneau2)", border:"1px solid var(--bordure)", borderRadius:10, padding:"7px 10px", fontSize:13, whiteSpace:"pre-wrap"}}>{m.affiche}</div>)} |
|
1137 |
+ {charge && <div style={{fontSize:12, color:"var(--texte3)"}}>Le recruteur consulte ses listes<span className="apparait">…</span></div>} |
|
1138 |
+ {erreur && <div style={{fontSize:12, color:"var(--rouge)"}}>{erreur}</div>} |
|
1139 |
+ <div ref={bas}/> |
|
1140 |
+ </div> |
|
1141 |
+ <div style={{display:"flex", gap:6, padding:10, borderTop:"1px solid var(--bordure)"}}> |
|
1142 |
+ <input value={saisie} onChange={e=>setSaisie(e.target.value)} onKeyDown={e=>e.key==="Enter"&&envoyer()} placeholder="Votre question…" aria-label="Question au recruteur-chef" |
|
1143 |
+ style={{flex:1, background:"var(--panneau2)", color:"var(--texte)", border:"1px solid var(--bordure)", borderRadius:8, padding:"8px 10px", fontSize:13}}/> |
|
1144 |
+ <button onClick={envoyer} disabled={charge} style={{background:"var(--glace)", color:"#04121F", border:"none", borderRadius:8, padding:"8px 12px", fontWeight:700, opacity:charge?0.5:1}}>➤</button> |
|
1145 |
+ </div> |
|
1146 |
+ </div> |
|
1147 |
+ : <button onClick={()=>setOuvert(true)} style={{background:"var(--glace)", color:"#04121F", border:"none", borderRadius:24, padding:"12px 18px", fontWeight:700, boxShadow:"0 6px 24px rgba(79,195,247,.35)"}}>💬 Chat analytique</button>} |
|
1148 |
+ </div>; |
|
1149 |
+} |
|
1150 |
+ |
|
1151 |
+/* ============================================================ |
|
1152 |
+ BOUTON « METTRE À JOUR LES DONNÉES » (web_search + JSON strict) |
|
1153 |
+ ============================================================ */ |
|
1154 |
+function BoutonMaj({onFusion, onToast}){ |
|
1155 |
+ const [charge, setCharge] = useState(false); |
|
1156 |
+ const [attente, setAttente] = useState(0); // anti-spam 60 s |
|
1157 |
+ useEffect(()=>{ if(attente<=0) return; const t=setTimeout(()=>setAttente(a=>a-1),1000); return ()=>clearTimeout(t); },[attente]); |
|
1158 |
+ const maj = async () => { |
|
1159 |
+ if(charge||attente>0) return; |
|
1160 |
+ setCharge(true); |
|
1161 |
+ try{ |
|
1162 |
+ const texte = await appelClaude([{role:"user", content:"Trouve les classements les plus récents du repêchage LNH 2027 (NHL Entry Draft 2027) et retourne UNIQUEMENT un JSON de la forme [{\"nom\":\"Prénom Nom\",\"rangConsensus\":1,\"sourcesRecentes\":\"source (date)\"}] pour les 32 meilleurs espoirs, sans aucun texte avant ou après, sans clôture de code."}], true, 1500); |
|
1163 |
+ let liste; |
|
1164 |
+ try{ liste = JSON.parse(nettoyerJSON(texte)); } |
|
1165 |
+ catch(e){ throw new Error("réponse non analysable en JSON"); } |
|
1166 |
+ if(!Array.isArray(liste) || liste.length===0) throw new Error("liste vide ou mal formée"); |
|
1167 |
+ onFusion(liste); |
|
1168 |
+ onToast({type:"succes", texte:`Données rafraîchies : ${liste.length} espoirs mis à jour (rangs et tendances fusionnés, fiches conservées).`}); |
|
1169 |
+ }catch(e){ |
|
1170 |
+ onToast({type:"echec", texte:"Échec de la mise à jour : " + e.message + ". Les données du 2026-08-08 restent affichées."}); |
|
1171 |
+ }finally{ setCharge(false); setAttente(60); } |
|
1172 |
+ }; |
|
1173 |
+ return <button onClick={maj} disabled={charge||attente>0} |
|
1174 |
+ style={{background:charge?"var(--panneau2)":"var(--glace)", color:charge?"var(--texte2)":"#04121F", border:"none", borderRadius:8, padding:"8px 14px", fontWeight:700, opacity:attente>0?0.55:1}}> |
|
1175 |
+ {charge ? "Recherche en cours…" : attente>0 ? `Mettre à jour (${attente} s)` : "⟳ Mettre à jour les données"} |
|
1176 |
+ </button>; |
|
1177 |
+} |
|
1178 |
+ |
|
1179 |
+/* ============================================================ |
|
1180 |
+ MODE MOCK DRAFT PERSONNALISÉ — drag-and-drop + boutons ↑↓ |
|
1181 |
+ (accessibilité clavier), analyse IA, export texte + image. |
|
1182 |
+ État en mémoire React uniquement (aucun localStorage). |
|
1183 |
+ ============================================================ */ |
|
1184 |
+function ModePerso({choixBase, onToast}){ |
|
1185 |
+ const [monOrdre, setMonOrdre] = useState(ORDRE_EDITORIAL.slice()); |
|
1186 |
+ const [filtreBanque, setFiltreBanque] = useState(""); |
|
1187 |
+ const [glisse, setGlisse] = useState(null); // id en cours de glissement |
|
1188 |
+ const [analyse, setAnalyse] = useState(null); |
|
1189 |
+ const [chargeAnalyse, setChargeAnalyse] = useState(false); |
|
1190 |
+ const canevas = useRef(null); |
|
1191 |
+ const banque = ESPOIRS.filter(e=>!monOrdre.includes(e.id) && e.nom.toLowerCase().includes(filtreBanque.toLowerCase())); |
|
1192 |
+ const deplacer = (i, delta) => { |
|
1193 |
+ const j = i+delta; if(j<0||j>=monOrdre.length) return; |
|
1194 |
+ const o = monOrdre.slice(); [o[i],o[j]]=[o[j],o[i]]; setMonOrdre(o); |
|
1195 |
+ }; |
|
1196 |
+ const surDepot = (iCible) => { |
|
1197 |
+ if(glisse==null) return; |
|
1198 |
+ const o = monOrdre.slice(); |
|
1199 |
+ const iSrc = o.indexOf(glisse); |
|
1200 |
+ if(iSrc>=0) o.splice(iSrc,1); // réordonner |
|
1201 |
+ o.splice(iCible,0,glisse); |
|
1202 |
+ setMonOrdre(o.slice(0,32)); // garder 32 choix |
|
1203 |
+ setGlisse(null); |
|
1204 |
+ }; |
|
1205 |
+ const retirer = (id) => setMonOrdre(monOrdre.filter(x=>x!==id)); |
|
1206 |
+ const analyser = async () => { |
|
1207 |
+ if(chargeAnalyse) return; |
|
1208 |
+ setChargeAnalyse(true); setAnalyse(null); |
|
1209 |
+ try{ |
|
1210 |
+ const mock = monOrdre.map((id,i)=>`${i+1}. ${EQUIPES[choixBase[i].detenteurActuel].nom} : ${parId[id].nom} (${parId[id].position}, consensus ${fmtRang(parId[id].rangConsensus)})`).join("\n"); |
|
1211 |
+ const texte = await appelClaude([{role:"user", content:`Tu es un recruteur-chef de la LNH. Voici le mock draft 2027 d'un utilisateur (ordre d'équipes simulé sur le classement 2025-26) :\n${mock}\n\nNote ce repêchage choix par choix, en français et brièvement : pour chacun des 10 premiers choix puis en survol pour 11-32, indique accord ✅ ou désaccord ❌ avec une justification d'une phrase (besoin organisationnel vs meilleur disponible). Termine par une note globale sur 10. N'invente aucune statistique.`}], false, 1400); |
|
1212 |
+ setAnalyse(texte); |
|
1213 |
+ }catch(e){ |
|
1214 |
+ setAnalyse(null); |
|
1215 |
+ onToast({type:"echec", texte:"Échec de l'analyse IA : " + e.message}); |
|
1216 |
+ }finally{ setChargeAnalyse(false); } |
|
1217 |
+ }; |
|
1218 |
+ const exporterTexte = () => { |
|
1219 |
+ const t = "MON MOCK DRAFT LNH 2027 — DraftVision (généré le "+META.dateGeneration+", ordre simulé)\n" + |
|
1220 |
+ monOrdre.map((id,i)=>`${String(i+1).padStart(2," ")}. ${choixBase[i].detenteurActuel} — ${parId[id].nom} (${parId[id].position}, ${parId[id].ligue})`).join("\n"); |
|
1221 |
+ navigator.clipboard.writeText(t).then( |
|
1222 |
+ ()=>onToast({type:"succes", texte:"Résumé texte copié dans le presse-papiers."}), |
|
1223 |
+ ()=>onToast({type:"echec", texte:"Impossible de copier — sélectionnez le texte manuellement dans la console."})); |
|
1224 |
+ }; |
|
1225 |
+ const exporterImage = () => { |
|
1226 |
+ const cv = canevas.current; const ctx = cv.getContext("2d"); |
|
1227 |
+ cv.width=800; cv.height=560; |
|
1228 |
+ ctx.fillStyle="#0A0E1A"; ctx.fillRect(0,0,800,560); |
|
1229 |
+ ctx.fillStyle="#4FC3F7"; ctx.font="700 34px 'Barlow Condensed', sans-serif"; |
|
1230 |
+ ctx.fillText("MON TOP-10 — MOCK DRAFT LNH 2027", 24, 48); |
|
1231 |
+ ctx.fillStyle="#93A1B8"; ctx.font="12px Inter, sans-serif"; |
|
1232 |
+ ctx.fillText("DraftVision 2027 · ordre simulé (classement 2025-26) · données du "+META.dateDonnees, 24, 70); |
|
1233 |
+ monOrdre.slice(0,10).forEach((id,i)=>{ |
|
1234 |
+ const e=parId[id], eq=EQUIPES[choixBase[i].detenteurActuel]; |
|
1235 |
+ const y=100+i*44; |
|
1236 |
+ ctx.fillStyle=eq.c1; ctx.fillRect(24,y-24,34,34); |
|
1237 |
+ ctx.fillStyle="#fff"; ctx.font="700 13px 'Barlow Condensed'"; ctx.fillText(choixBase[i].detenteurActuel, 27, y-3); |
|
1238 |
+ ctx.fillStyle="#4FC3F7"; ctx.font="700 20px 'Barlow Condensed'"; ctx.fillText(String(i+1), 72, y); |
|
1239 |
+ ctx.fillStyle="#E5EAF2"; ctx.font="600 16px Inter"; ctx.fillText(e.nom, 104, y); |
|
1240 |
+ ctx.fillStyle="#93A1B8"; ctx.font="12px Inter"; ctx.fillText(`${e.position} · ${e.ligue}${e.stats.pts!=null?` · ${e.stats.pts} pts en ${e.stats.mj} MJ (2025-26)`:""}`, 104+ctx.measureText(e.nom).width+180<800?360:360, y); |
|
1241 |
+ }); |
|
1242 |
+ const lien=document.createElement("a"); |
|
1243 |
+ lien.download="mon-top10-draftvision2027.png"; lien.href=cv.toDataURL("image/png"); lien.click(); |
|
1244 |
+ onToast({type:"succes", texte:"Image du top-10 téléchargée."}); |
|
1245 |
+ }; |
|
1246 |
+ return <section aria-label="Mode mock draft personnalisé" className="apparait" style={{background:"var(--panneau)", border:"1px solid var(--bordure)", borderRadius:12, padding:16, marginBottom:14}}> |
|
1247 |
+ <div style={{display:"flex", justifyContent:"space-between", flexWrap:"wrap", gap:8, alignItems:"center", marginBottom:8}}> |
|
1248 |
+ <h2 style={{fontSize:20}}>✏️ Mon mock draft <span style={{fontSize:12, color:"var(--texte3)", fontWeight:400}}>— glisser-déposer, ou boutons ↑↓ au clavier</span></h2> |
|
1249 |
+ <div style={{display:"flex", gap:8, flexWrap:"wrap"}}> |
|
1250 |
+ <button onClick={analyser} disabled={chargeAnalyse} style={{background:"var(--glace)", color:"#04121F", border:"none", borderRadius:8, padding:"7px 12px", fontWeight:700, opacity:chargeAnalyse?0.5:1}}>{chargeAnalyse?"Analyse en cours…":"🧠 Analyser mon repêchage"}</button> |
|
1251 |
+ <button onClick={exporterTexte} style={{background:"none", color:"var(--texte2)", border:"1px solid var(--bordure)", borderRadius:8, padding:"7px 12px"}}>Copier le résumé</button> |
|
1252 |
+ <button onClick={exporterImage} style={{background:"none", color:"var(--texte2)", border:"1px solid var(--bordure)", borderRadius:8, padding:"7px 12px"}}>Image du top-10</button> |
|
1253 |
+ <button onClick={()=>setMonOrdre(ORDRE_EDITORIAL.slice())} style={{background:"none", color:"var(--texte2)", border:"1px solid var(--bordure)", borderRadius:8, padding:"7px 12px"}}>Réinitialiser</button> |
|
1254 |
+ </div> |
|
1255 |
+ </div> |
|
1256 |
+ <div style={{display:"grid", gridTemplateColumns:"minmax(0,2fr) minmax(0,1fr)", gap:12}} className="grille-perso"> |
|
1257 |
+ <ol style={{listStyle:"none"}} aria-label="Mes 32 choix"> |
|
1258 |
+ {monOrdre.map((id,i)=>{const e=parId[id]; const c=choixBase[i]; return <li key={id} draggable |
|
1259 |
+ onDragStart={()=>setGlisse(id)} onDragOver={ev=>ev.preventDefault()} onDrop={()=>surDepot(i)} |
|
1260 |
+ style={{display:"flex", alignItems:"center", gap:8, padding:"5px 8px", marginBottom:4, background:glisse===id?"rgba(79,195,247,.12)":"var(--panneau2)", border:"1px solid var(--bordure)", borderRadius:8, cursor:"grab"}}> |
|
1261 |
+ <span className="num titre" style={{width:24, textAlign:"center", fontWeight:700, color:"var(--texte2)"}}>{i+1}</span> |
|
1262 |
+ <Ecusson abbr={c.detenteurActuel} taille={26}/> |
|
1263 |
+ <span style={{flex:1, fontSize:13}}><b>{e.nom}</b> <span style={{color:"var(--texte2)", fontSize:11}}>{e.position} · {e.ligue} · consensus {fmtRang(e.rangConsensus)}</span></span> |
|
1264 |
+ <button onClick={()=>deplacer(i,-1)} aria-label={`Monter ${e.nom}`} style={{background:"none", border:"1px solid var(--bordure)", color:"var(--texte2)", borderRadius:5, width:24, height:24}}>↑</button> |
|
1265 |
+ <button onClick={()=>deplacer(i,1)} aria-label={`Descendre ${e.nom}`} style={{background:"none", border:"1px solid var(--bordure)", color:"var(--texte2)", borderRadius:5, width:24, height:24}}>↓</button> |
|
1266 |
+ <button onClick={()=>retirer(id)} aria-label={`Retirer ${e.nom}`} style={{background:"none", border:"1px solid var(--bordure)", color:"var(--rouge)", borderRadius:5, width:24, height:24}}>✕</button> |
|
1267 |
+ </li>;})} |
|
1268 |
+ </ol> |
|
1269 |
+ <div> |
|
1270 |
+ <h3 style={{fontSize:14, marginBottom:6}}>Banque de joueurs disponibles ({banque.length})</h3> |
|
1271 |
+ <input type="search" placeholder="Filtrer la banque…" value={filtreBanque} onChange={e=>setFiltreBanque(e.target.value)} aria-label="Filtrer la banque de joueurs" |
|
1272 |
+ style={{width:"100%", background:"var(--panneau2)", color:"var(--texte)", border:"1px solid var(--bordure)", borderRadius:6, padding:"6px 8px", fontSize:12, marginBottom:6}}/> |
|
1273 |
+ <div style={{maxHeight:420, overflowY:"auto", display:"flex", flexDirection:"column", gap:4}}> |
|
1274 |
+ {banque.map(e=><div key={e.id} draggable onDragStart={()=>setGlisse(e.id)} |
|
1275 |
+ style={{display:"flex", alignItems:"center", gap:6, padding:"4px 8px", background:"var(--panneau2)", border:"1px dashed var(--bordure)", borderRadius:8, cursor:"grab", fontSize:12}}> |
|
1276 |
+ <Avatar esp={e} taille={24}/><span style={{flex:1}}>{e.nom} <span style={{color:"var(--texte3)"}}>{e.position} · consensus {fmtRang(e.rangConsensus)}</span></span> |
|
1277 |
+ <button onClick={()=>setMonOrdre([...monOrdre, e.id].slice(0,32))} aria-label={`Ajouter ${e.nom} à la fin de mon mock`} style={{background:"none", border:"1px solid var(--bordure)", color:"var(--vert)", borderRadius:5, width:22, height:22}}>+</button> |
|
1278 |
+ </div>)} |
|
1279 |
+ </div> |
|
1280 |
+ </div> |
|
1281 |
+ </div> |
|
1282 |
+ {analyse && <div className="apparait" style={{marginTop:10, background:"var(--panneau2)", border:"1px solid var(--glace)", borderRadius:8, padding:12, fontSize:13, whiteSpace:"pre-wrap", color:"var(--texte2)"}}>{analyse}</div>} |
|
1283 |
+ <canvas ref={canevas} style={{display:"none"}} aria-hidden="true"/> |
|
1284 |
+ </section>; |
|
1285 |
+} |
|
1286 |
+ |
|
1287 |
+/* ============================================================ |
|
1288 |
+ APPLICATION |
|
1289 |
+ ============================================================ */ |
|
1290 |
+function Toast({toast}){ |
|
1291 |
+ if(!toast) return null; |
|
1292 |
+ return <div role="status" className="apparait" style={{position:"fixed", left:"50%", transform:"translateX(-50%)", bottom:18, zIndex:60, |
|
1293 |
+ background:toast.type==="succes"?"rgba(34,197,94,.14)":"rgba(239,68,68,.14)", border:`1px solid ${toast.type==="succes"?"var(--vert)":"var(--rouge)"}`, |
|
1294 |
+ color:"var(--texte)", borderRadius:10, padding:"10px 16px", fontSize:13, maxWidth:"min(560px, 90vw)"}}>{toast.texte}</div>; |
|
1295 |
+} |
|
1296 |
+ |
|
1297 |
+function App(){ |
|
1298 |
+ const [ordreHS, setOrdreHS] = useState(ORDRE_HORS_SERIES); // 16 équipes hors séries (réordonnées par loterie) |
|
1299 |
+ const [apresLoterie, setApresLoterie] = useState(false); |
|
1300 |
+ const [historique, setHistorique] = useState([]); // 5 dernières simulations |
|
1301 |
+ const [noSim, setNoSim] = useState(0); |
|
1302 |
+ const [selection, setSelection] = useState(null); // id espoir sélectionné |
|
1303 |
+ const [vue, setVue] = useState("mock"); // mock | perso | sleepers |
|
1304 |
+ const [f, setF] = useState({recherche:"", position:"Tous", ligue:"Toutes", nationalite:"Toutes", risque:"Tous", tendance:"Toutes", tri:"consensus"}); |
|
1305 |
+ const [majRangs, setMajRangs] = useState(null); // fusion du bouton MàJ |
|
1306 |
+ const [dateMaj, setDateMaj] = useState(META.dateDonnees); |
|
1307 |
+ const [toast, setToast] = useState(null); |
|
1308 |
+ useEffect(()=>{ if(!toast) return; const t=setTimeout(()=>setToast(null), 5000); return ()=>clearTimeout(t); },[toast]); |
|
1309 |
+ |
|
1310 |
+ const choix = useMemo(()=>{ |
|
1311 |
+ const base = construireOrdre(ordreHS); |
|
1312 |
+ return base.map(c=>({...c, logique: apresLoterie |
|
1313 |
+ ? (c.joueurProjete ? `Ordre réorganisé par la loterie simulée — attribution recalculée : meilleur talent disponible au tableau éditorial. Banque de ${EQUIPES[c.detenteurActuel].nom} — forces : ${EQUIPES[c.detenteurActuel].banque.forces} Lacunes : ${EQUIPES[c.detenteurActuel].banque.lacunes}` : "") |
|
1314 |
+ : (LOGIQUES_BASE[c.rang] ? LOGIQUES_BASE[c.rang].txt : ""), |
|
1315 |
+ autresOptions: !apresLoterie && LOGIQUES_BASE[c.rang] ? LOGIQUES_BASE[c.rang].b : null})); |
|
1316 |
+ },[ordreHS, apresLoterie]); |
|
1317 |
+ |
|
1318 |
+ // Filtrage appliqué au tableau du mock (les rangées dont le joueur ne passe pas le filtre sont estompées) |
|
1319 |
+ const idsFiltres = useMemo(()=>new Set(filtrerEspoirs(ESPOIRS, f).map(e=>e.id)),[f]); |
|
1320 |
+ const espSelection = selection ? parId[selection] : null; |
|
1321 |
+ const choixSelection = espSelection ? choix.find(c=>c.joueurProjete===espSelection.id) : null; |
|
1322 |
+ |
|
1323 |
+ const surLoterie = (res)=>{ |
|
1324 |
+ setOrdreHS(res.ordre); setApresLoterie(true); setNoSim(n=>n+1); |
|
1325 |
+ setHistorique(h=>[{gagnant1:res.gagnant1, gagnant2:res.gagnant2}, ...h].slice(0,5)); |
|
1326 |
+ }; |
|
1327 |
+ const surFusion = (liste)=>{ |
|
1328 |
+ // Fusion intelligente : rangs/tendances mis à jour, fiches conservées. |
|
1329 |
+ let touches = 0; |
|
1330 |
+ liste.forEach(item=>{ |
|
1331 |
+ const e = ESPOIRS.find(x=>x.nom.toLowerCase()===String(item.nom||"").toLowerCase()); |
|
1332 |
+ if(e && Number.isFinite(item.rangConsensus)){ |
|
1333 |
+ e.tendance = item.rangConsensus < (e.rangConsensus??99) - 1 ? "up" : item.rangConsensus > (e.rangConsensus??0) + 1 ? "down" : e.tendance; |
|
1334 |
+ e.rangConsensus = item.rangConsensus; |
|
1335 |
+ e.majRecente = item.sourcesRecentes || "mise à jour IA"; |
|
1336 |
+ touches++; |
|
1337 |
+ } |
|
1338 |
+ }); |
|
1339 |
+ setMajRangs({n:touches, quand:new Date().toISOString().slice(0,10)}); |
|
1340 |
+ setDateMaj(new Date().toISOString().slice(0,10)); |
|
1341 |
+ }; |
|
1342 |
+ |
|
1343 |
+ return <div style={{maxWidth:1240, margin:"0 auto", padding:"14px 14px 80px"}}> |
|
1344 |
+ <header style={{display:"flex", justifyContent:"space-between", alignItems:"center", flexWrap:"wrap", gap:10, marginBottom:10}}> |
|
1345 |
+ <div> |
|
1346 |
+ <h1 style={{fontSize:38, lineHeight:1, color:"var(--glace)", textTransform:"uppercase"}}>DraftVision <span style={{color:"var(--texte)"}}>2027</span></h1> |
|
1347 |
+ <div style={{fontSize:12, color:"var(--texte2)"}}>Prévision de la 1re ronde du repêchage LNH 2027 · données du <b className="num">{dateMaj}</b> · générée le <span className="num">{META.dateGeneration}</span>{majRangs && <span style={{color:"var(--vert)"}}> · {majRangs.n} rangs rafraîchis via IA</span>}</div> |
|
1348 |
+ </div> |
|
1349 |
+ <BoutonMaj onFusion={surFusion} onToast={setToast}/> |
|
1350 |
+ </header> |
|
1351 |
+ |
|
1352 |
+ <div role="alert" style={{background:"rgba(245,158,11,.10)", border:"1px solid var(--ambre)", borderRadius:10, padding:"8px 12px", fontSize:12, color:"var(--texte2)", marginBottom:10}}> |
|
1353 |
+ ⚠️ <b style={{color:"var(--ambre)"}}>Projection, pas une prédiction :</b> la loterie 2027 n'a pas eu lieu et la saison 2026-27 n'a pas commencé — ordre basé sur le classement final 2025-26 {apresLoterie ? "+ LOTERIE SIMULÉE (fictive)" : "(pré-loterie)"} ; date/lieu du repêchage 2027 non annoncés ; classements d'espoirs « way-too-early » (mars-juillet 2026). Aucun gardien n'est classé par les sources → aucun gardien projeté. 2e ronde omise : sources insuffisantes pour 64 choix fiables. |
|
1354 |
+ </div> |
|
1355 |
+ |
|
1356 |
+ <nav aria-label="Sections" style={{display:"flex", gap:8, marginBottom:12, flexWrap:"wrap"}}> |
|
1357 |
+ {[["mock","📋 Mock draft"],["perso","✏️ Mode personnalisé"],["sleepers","💎 Sleepers et chutes"]].map(([v,l])=> |
|
1358 |
+ <button key={v} onClick={()=>setVue(v)} aria-pressed={vue===v} |
|
1359 |
+ style={{background:vue===v?"var(--glace)":"var(--panneau)", color:vue===v?"#04121F":"var(--texte2)", border:"1px solid var(--bordure)", borderRadius:8, padding:"8px 14px", fontWeight:600}}>{l}</button>)} |
|
1360 |
+ </nav> |
|
1361 |
+ |
|
1362 |
+ {vue==="mock" && <> |
|
1363 |
+ <PanneauLoterie onResultat={surLoterie} onReinit={()=>{setOrdreHS(ORDRE_HORS_SERIES); setApresLoterie(false);}} historique={historique} noSim={noSim}/> |
|
1364 |
+ <BarreFiltres f={f} setF={setF} liste={ESPOIRS}/> |
|
1365 |
+ <div style={{display:"grid", gridTemplateColumns: espSelection ? "minmax(0,1.4fr) minmax(300px,1fr)" : "1fr", gap:14}} className="grille-mock"> |
|
1366 |
+ <div> |
|
1367 |
+ {choix.map(c=>{ |
|
1368 |
+ const e = c.joueurProjete ? parId[c.joueurProjete] : null; |
|
1369 |
+ const passe = !e || idsFiltres.has(e.id); |
|
1370 |
+ return <div key={c.rang} style={{opacity:passe?1:0.25, transition:"opacity .2s"}}> |
|
1371 |
+ <RangeeChoix choix={c} esp={e} selection={espSelection && e && espSelection.id===e.id} onSelection={()=>e && setSelection(e.id===selection?null:e.id)} apresLoterie={apresLoterie}/> |
|
1372 |
+ </div>;})} |
|
1373 |
+ <details style={{marginTop:10, background:"var(--panneau)", border:"1px solid var(--bordure)", borderRadius:10, padding:"8px 12px"}}> |
|
1374 |
+ <summary style={{cursor:"pointer", fontSize:13, color:"var(--texte2)"}}>Hors première ronde — autres espoirs suivis ({ESPOIRS.filter(e=>!ORDRE_EDITORIAL.includes(e.id)).length})</summary> |
|
1375 |
+ <div style={{marginTop:8}}> |
|
1376 |
+ {filtrerEspoirs(ESPOIRS.filter(e=>!ORDRE_EDITORIAL.includes(e.id)), f).map(e=> |
|
1377 |
+ <div key={e.id} role="button" tabIndex={0} onClick={()=>setSelection(e.id===selection?null:e.id)} onKeyDown={ev=>{if(ev.key==="Enter"){setSelection(e.id);}}} |
|
1378 |
+ style={{display:"flex", alignItems:"center", gap:8, padding:"5px 8px", borderRadius:8, cursor:"pointer", border:"1px solid transparent"}}> |
|
1379 |
+ <Avatar esp={e} taille={28}/> |
|
1380 |
+ <span style={{fontSize:13, flex:1}}><b>{e.nom}</b> <span style={{color:"var(--texte2)", fontSize:11}}>{e.position} · {e.ligue} · consensus {fmtRang(e.rangConsensus)}</span></span> |
|
1381 |
+ <BadgeVolatil esp={e}/><BadgeTendance t={e.tendance}/> |
|
1382 |
+ </div>)} |
|
1383 |
+ </div> |
|
1384 |
+ </details> |
|
1385 |
+ </div> |
|
1386 |
+ {espSelection && <Fiche esp={espSelection} choix={choixSelection} onFermer={()=>setSelection(null)}/>} |
|
1387 |
+ </div> |
|
1388 |
+ </>} |
|
1389 |
+ {vue==="perso" && <ModePerso choixBase={choix} onToast={setToast}/>} |
|
1390 |
+ {vue==="sleepers" && <SectionSleepers onVoir={id=>{setSelection(id); setVue("mock"); window.scrollTo({top:0, behavior:"smooth"});}}/>} |
|
1391 |
+ |
|
1392 |
+ <footer style={{marginTop:24, borderTop:"1px solid var(--bordure)", paddingTop:14, fontSize:12, color:"var(--texte3)"}}> |
|
1393 |
+ <h3 style={{fontSize:15, color:"var(--texte2)", marginBottom:6}}>Sources consultées (pipeline du {META.dateGeneration})</h3> |
|
1394 |
+ <ul style={{paddingLeft:18, display:"grid", gridTemplateColumns:"repeat(auto-fill, minmax(320px,1fr))", gap:"2px 16px"}}> |
|
1395 |
+ {SOURCES.map(s=><li key={s.cle}>{s.nom} — {s.date} (poids {s.poids} %)</li>)} |
|
1396 |
+ <li>Statistiques : Elite Prospects Draft Center, Tankathon, NHL.com, usahockeyntdp.com, hockeydb, CHL.ca — consultés le 2026-08-08</li> |
|
1397 |
+ <li>Ordre/loterie : Daily Faceoff (avril 2026), NHL.com, ESPN (ordre du repêchage 2026)</li> |
|
1398 |
+ <li>Picks échangés : Wikipedia « 2027 NHL entry draft », PuckPedia, NHL.com, Pro Hockey Rumors — consultés le 2026-08-08</li> |
|
1399 |
+ <li>Banques d'espoirs : {BANQUE_SOURCE}</li> |
|
1400 |
+ <li>Momentum et ajustements Hlinka-Gretzky 2026 : TSN/La Presse Canadienne, Sportsnet, CHL.ca, Daily Faceoff (tournoi du 3-8 août 2026, finale Canada 8-1 USA) — ajustements bornés ±3 rangs sur le consensus, détaillés dans chaque fiche 🏆</li> |
|
1401 |
+ </ul> |
|
1402 |
+ <p style={{marginTop:8}}>Sources non publiées pour 2027 (retirées du consensus) : {SOURCES_NON_PUBLIEES.join(" · ")}.</p> |
|
1403 |
+ <p style={{marginTop:8}}>Documents compagnons : <a href="/ADMIN-REPECHAGE-2027.md">Administration du repêchage 2027 (CBA, loterie, jalons)</a> · <a href="/COULISSES-2027.txt">Coulisses 2027 — notes d'initié sourcées (contrats KHL, exode NTDP, NIL, clauses cachées)</a> · <a href="/RECHERCHE.md">Journal méthodologique du pipeline de recherche</a>.</p> |
|
1404 |
+ <p style={{marginTop:8}}>Logos d'équipes : marques officielles de la LNH et de ses clubs (servies depuis assets.nhle.com), utilisées à des fins d'identification éditoriale — site non affilié à la LNH. Aucune photo de joueur. Analyses, forces et faiblesses : synthèses originales de DraftVision. Les espoirs sont des adolescents : évaluations strictement sportives. Auteur : Simon-Pierre Boucher — contact@spboucher.ai</p> |
|
1405 |
+ <details style={{marginTop:8}}> |
|
1406 |
+ <summary style={{cursor:"pointer"}}>Avertissements méthodologiques complets</summary> |
|
1407 |
+ <ul style={{paddingLeft:18, marginTop:4}}>{META.avertissements.map((a,i)=><li key={i}>{a}</li>)}</ul> |
|
1408 |
+ </details> |
|
1409 |
+ </footer> |
|
1410 |
+ |
|
1411 |
+ <Chat choix={choix}/> |
|
1412 |
+ <Toast toast={toast}/> |
|
1413 |
+ <style>{` |
|
1414 |
+ @media (max-width: 900px){ .grille-mock{grid-template-columns:1fr !important;} .grille-perso{grid-template-columns:1fr !important;} } |
|
1415 |
+ @media (max-width: 768px){ h1{font-size:30px !important;} } |
|
1416 |
+ `}</style> |
|
1417 |
+ </div>; |
|
1418 |
+} |
|
1419 |
+ReactDOM.createRoot(document.getElementById("racine")).render(<App/>); |
|
1420 |
+</script> |
|
1421 |
+</body> |
|
1422 |
+</html> |