Spaces:
Running
Running
| <html lang="fr"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Devine la Mante | Jeu Géographique</title> | |
| <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" /> | |
| <link href="https://fonts.googleapis.com/css2?family=Crimson+Pro:wght@400;600;700&family=Source+Sans+3:wght@300;400;600&display=swap" rel="stylesheet"> | |
| <style> | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| :root { | |
| --sepia: #f4f1e8; | |
| --dark-sepia: #3d3526; | |
| --accent-green: #4a7c59; | |
| --accent-gold: #d4a574; | |
| --shadow: rgba(61, 53, 38, 0.15); | |
| --border: rgba(61, 53, 38, 0.2); | |
| } | |
| body { | |
| font-family: 'Source Sans 3', sans-serif; | |
| background: linear-gradient(135deg, #f4f1e8 0%, #e8e3d6 100%); | |
| color: var(--dark-sepia); | |
| overflow-x: hidden; | |
| min-height: 100vh; | |
| } | |
| body::before { | |
| content: ''; | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background-image: | |
| repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(61, 53, 38, 0.03) 2px, rgba(61, 53, 38, 0.03) 4px), | |
| repeating-linear-gradient(90deg, transparent, transparent 2px, rgba(61, 53, 38, 0.03) 2px, rgba(61, 53, 38, 0.03) 4px); | |
| pointer-events: none; | |
| z-index: 1; | |
| opacity: 0.3; | |
| } | |
| .container { | |
| max-width: 1400px; | |
| margin: 0 auto; | |
| padding: 2rem; | |
| position: relative; | |
| z-index: 2; | |
| } | |
| header { | |
| text-align: center; | |
| margin-bottom: 3rem; | |
| animation: fadeInDown 1s ease; | |
| } | |
| h1 { | |
| font-family: 'Crimson Pro', serif; | |
| font-size: 3.5rem; | |
| font-weight: 700; | |
| color: var(--accent-green); | |
| letter-spacing: -0.02em; | |
| margin-bottom: 0.5rem; | |
| text-shadow: 2px 2px 4px rgba(0,0,0,0.1); | |
| } | |
| .subtitle { | |
| font-size: 1.1rem; | |
| color: var(--dark-sepia); | |
| opacity: 0.8; | |
| font-style: italic; | |
| } | |
| .stats-bar { | |
| display: flex; | |
| justify-content: center; | |
| gap: 2rem; | |
| margin-top: 1rem; | |
| font-size: 0.95rem; | |
| color: var(--dark-sepia); | |
| opacity: 0.7; | |
| } | |
| .game-container { | |
| display: grid; | |
| grid-template-columns: 1fr 400px; | |
| gap: 2rem; | |
| animation: fadeInUp 1s ease 0.2s both; | |
| } | |
| .map-panel { | |
| background: white; | |
| border-radius: 16px; | |
| box-shadow: | |
| 0 10px 40px var(--shadow), | |
| inset 0 0 0 1px var(--border); | |
| overflow: hidden; | |
| position: relative; | |
| } | |
| .map-header { | |
| background: linear-gradient(135deg, var(--accent-green) 0%, #5a8c69 100%); | |
| color: white; | |
| padding: 1.5rem 2rem; | |
| font-family: 'Crimson Pro', serif; | |
| font-size: 1.4rem; | |
| font-weight: 600; | |
| letter-spacing: 0.02em; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| } | |
| .map-controls { | |
| display: flex; | |
| gap: 0.5rem; | |
| } | |
| .map-type-btn { | |
| background: rgba(255, 255, 255, 0.2); | |
| border: 2px solid rgba(255, 255, 255, 0.3); | |
| color: white; | |
| padding: 0.5rem 1rem; | |
| border-radius: 6px; | |
| font-family: 'Source Sans 3', sans-serif; | |
| font-size: 0.85rem; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| } | |
| .map-type-btn:hover { | |
| background: rgba(255, 255, 255, 0.3); | |
| border-color: rgba(255, 255, 255, 0.5); | |
| } | |
| .map-type-btn.active { | |
| background: white; | |
| color: var(--accent-green); | |
| border-color: white; | |
| } | |
| #map { | |
| height: 600px; | |
| width: 100%; | |
| background: #a8c5d9; | |
| } | |
| .control-panel { | |
| background: white; | |
| border-radius: 16px; | |
| box-shadow: | |
| 0 10px 40px var(--shadow), | |
| inset 0 0 0 1px var(--border); | |
| padding: 2rem; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 1.5rem; | |
| max-height: 800px; | |
| overflow-y: auto; | |
| } | |
| .score-display { | |
| background: linear-gradient(135deg, #f8f6f0 0%, #ede9dc 100%); | |
| padding: 1.5rem; | |
| border-radius: 10px; | |
| text-align: center; | |
| border: 2px solid var(--border); | |
| position: sticky; | |
| top: 0; | |
| z-index: 10; | |
| } | |
| .score-label { | |
| font-family: 'Crimson Pro', serif; | |
| font-size: 0.9rem; | |
| color: var(--dark-sepia); | |
| opacity: 0.7; | |
| text-transform: uppercase; | |
| letter-spacing: 0.1em; | |
| margin-bottom: 0.5rem; | |
| } | |
| .score-value { | |
| font-size: 2.5rem; | |
| font-weight: 700; | |
| color: var(--accent-green); | |
| font-family: 'Crimson Pro', serif; | |
| } | |
| .answer-input-section { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 1rem; | |
| } | |
| .answer-input-section label { | |
| font-family: 'Crimson Pro', serif; | |
| font-size: 1.1rem; | |
| font-weight: 600; | |
| color: var(--accent-green); | |
| } | |
| .input-wrapper { | |
| position: relative; | |
| } | |
| #species-input { | |
| width: 100%; | |
| padding: 1rem; | |
| border: 2px solid var(--border); | |
| border-radius: 10px; | |
| font-family: 'Crimson Pro', serif; | |
| font-size: 1rem; | |
| background: var(--sepia); | |
| color: var(--dark-sepia); | |
| transition: all 0.3s ease; | |
| } | |
| #species-input:focus { | |
| outline: none; | |
| border-color: var(--accent-green); | |
| background: white; | |
| box-shadow: 0 4px 12px var(--shadow); | |
| } | |
| .autocomplete-dropdown { | |
| position: absolute; | |
| top: 100%; | |
| left: 0; | |
| right: 0; | |
| background: white; | |
| border: 2px solid var(--accent-green); | |
| border-top: none; | |
| border-radius: 0 0 10px 10px; | |
| max-height: 300px; | |
| overflow-y: auto; | |
| z-index: 1000; | |
| box-shadow: 0 8px 16px var(--shadow); | |
| } | |
| .autocomplete-item { | |
| padding: 0.75rem 1rem; | |
| cursor: pointer; | |
| transition: background 0.2s ease; | |
| border-bottom: 1px solid var(--border); | |
| } | |
| .autocomplete-item:last-child { | |
| border-bottom: none; | |
| } | |
| .autocomplete-item:hover, | |
| .autocomplete-item.selected { | |
| background: var(--sepia); | |
| } | |
| .autocomplete-item strong { | |
| color: var(--accent-green); | |
| display: block; | |
| margin-bottom: 0.25rem; | |
| } | |
| .autocomplete-item em { | |
| color: var(--dark-sepia); | |
| opacity: 0.7; | |
| font-size: 0.9rem; | |
| } | |
| .submit-btn { | |
| background: linear-gradient(135deg, var(--accent-green) 0%, #5a8c69 100%); | |
| color: white; | |
| border: none; | |
| padding: 1rem 1.5rem; | |
| border-radius: 10px; | |
| font-family: 'Crimson Pro', serif; | |
| font-size: 1.1rem; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| box-shadow: 0 4px 12px rgba(74, 124, 89, 0.3); | |
| } | |
| .submit-btn:hover:not(:disabled) { | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 20px rgba(74, 124, 89, 0.4); | |
| } | |
| .submit-btn:disabled { | |
| opacity: 0.5; | |
| cursor: not-allowed; | |
| } | |
| .hints-section { | |
| border-top: 2px solid var(--border); | |
| padding-top: 1.5rem; | |
| } | |
| .hint-btn { | |
| background: linear-gradient(135deg, var(--accent-gold) 0%, #c49564 100%); | |
| color: white; | |
| border: none; | |
| padding: 1rem 1.5rem; | |
| border-radius: 10px; | |
| font-family: 'Crimson Pro', serif; | |
| font-size: 1.1rem; | |
| font-weight: 600; | |
| cursor: pointer; | |
| width: 100%; | |
| transition: all 0.3s ease; | |
| box-shadow: 0 4px 12px rgba(212, 165, 116, 0.3); | |
| } | |
| .hint-btn:hover:not(:disabled) { | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 20px rgba(212, 165, 116, 0.4); | |
| } | |
| .hint-btn:disabled { | |
| opacity: 0.5; | |
| cursor: not-allowed; | |
| } | |
| .hints-display { | |
| margin-top: 1rem; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 0.75rem; | |
| } | |
| .hint-item { | |
| background: #fff9f0; | |
| border-left: 4px solid var(--accent-gold); | |
| padding: 1rem; | |
| border-radius: 6px; | |
| font-size: 0.95rem; | |
| line-height: 1.6; | |
| animation: slideInRight 0.4s ease; | |
| } | |
| .hint-label { | |
| font-weight: 600; | |
| color: var(--accent-green); | |
| margin-bottom: 0.25rem; | |
| } | |
| .next-btn { | |
| background: var(--accent-green); | |
| color: white; | |
| border: none; | |
| padding: 1rem 1.5rem; | |
| border-radius: 10px; | |
| font-family: 'Crimson Pro', serif; | |
| font-size: 1.1rem; | |
| font-weight: 600; | |
| cursor: pointer; | |
| width: 100%; | |
| transition: all 0.3s ease; | |
| box-shadow: 0 4px 12px rgba(74, 124, 89, 0.3); | |
| } | |
| .next-btn:hover { | |
| background: #5a8c69; | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 20px rgba(74, 124, 89, 0.4); | |
| } | |
| .result-message { | |
| padding: 1.5rem; | |
| border-radius: 10px; | |
| text-align: center; | |
| font-family: 'Crimson Pro', serif; | |
| font-size: 1.2rem; | |
| font-weight: 600; | |
| animation: fadeIn 0.5s ease; | |
| } | |
| .result-message.correct { | |
| background: rgba(74, 124, 89, 0.1); | |
| color: var(--accent-green); | |
| border: 2px solid var(--accent-green); | |
| } | |
| .result-message.incorrect { | |
| background: rgba(197, 74, 74, 0.1); | |
| color: #c54a4a; | |
| border: 2px solid #c54a4a; | |
| } | |
| @keyframes fadeInDown { | |
| from { | |
| opacity: 0; | |
| transform: translateY(-30px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| @keyframes fadeInUp { | |
| from { | |
| opacity: 0; | |
| transform: translateY(30px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| @keyframes slideInRight { | |
| from { | |
| opacity: 0; | |
| transform: translateX(-20px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateX(0); | |
| } | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; } | |
| to { opacity: 1; } | |
| } | |
| @media (max-width: 1024px) { | |
| .game-container { | |
| grid-template-columns: 1fr; | |
| } | |
| h1 { | |
| font-size: 2.5rem; | |
| } | |
| #map { | |
| height: 500px; | |
| } | |
| } | |
| .leaflet-control-attribution { | |
| background: rgba(255, 255, 255, 0.8) ; | |
| font-size: 0.7rem ; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <header> | |
| <h1>🦗 Devine la Mante</h1> | |
| <p class="subtitle">Identifie l'espèce selon sa distribution géographique</p> | |
| <div class="stats-bar"> | |
| <span>📊 <span id="total-species">60</span> espèces disponibles</span> | |
| </div> | |
| </header> | |
| <div class="game-container"> | |
| <div class="map-panel"> | |
| <div class="map-header"> | |
| <span>Distribution Mondiale des Occurrences</span> | |
| <div class="map-controls"> | |
| <button class="map-type-btn active" data-map="standard">Standard</button> | |
| <button class="map-type-btn" data-map="dark">Sombre</button> | |
| <button class="map-type-btn" data-map="satellite">Satellite</button> | |
| </div> | |
| </div> | |
| <div id="map"></div> | |
| </div> | |
| <div class="control-panel"> | |
| <div class="score-display"> | |
| <div class="score-label">Score</div> | |
| <div class="score-value" id="score">0</div> | |
| </div> | |
| <div id="result-container"></div> | |
| <div class="answer-input-section"> | |
| <label for="species-input">Quelle est cette espèce ?</label> | |
| <div class="input-wrapper"> | |
| <input | |
| type="text" | |
| id="species-input" | |
| placeholder="Tapez le nom de l'espèce..." | |
| autocomplete="off" | |
| /> | |
| <div id="autocomplete-dropdown" class="autocomplete-dropdown" style="display: none;"></div> | |
| </div> | |
| <button class="submit-btn" id="submit-btn"> | |
| Valider ma réponse | |
| </button> | |
| </div> | |
| <div class="hints-section"> | |
| <button class="hint-btn" id="hint-btn"> | |
| 💡 Demander un indice | |
| </button> | |
| <div class="hints-display" id="hints-display"></div> | |
| </div> | |
| <button class="next-btn" id="next-btn" style="display: none;"> | |
| Mante Suivante → | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> | |
| <script> | |
| // Complete species database with verified GBIF taxonKeys | |
| const speciesData = [ | |
| { | |
| name: "Mantis religiosa", | |
| commonName: "Mante religieuse", | |
| taxonKey: "6258028", | |
| family: "Mantidae", | |
| region: "Europe, Asie, introduite Amérique du Nord", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Europe, Asie, introduite en Amérique du Nord", | |
| "L'espèce de mante la plus commune et répandue en Europe, posture de prière caractéristique" | |
| ] | |
| }, | |
| { | |
| name: "Acontista mexicana", | |
| commonName: "Mante mexicaine", | |
| taxonKey: "1404204", | |
| family: "Acontistidae", | |
| region: "Amérique centrale", | |
| hints: [ | |
| "Famille : Acontistidae", | |
| "Distribution : Amérique centrale, notamment Mexique", | |
| "Petite mante discrète vivant dans les zones arides mexicaines" | |
| ] | |
| }, | |
| { | |
| name: "Macromantis hyalina", | |
| commonName: "Mante hyaline", | |
| taxonKey: "1405821", | |
| family: "Mantidae", | |
| region: "Amérique du Sud", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Amérique du Sud", | |
| "Grande mante aux ailes transparentes, typique des forêts tropicales" | |
| ] | |
| }, | |
| { | |
| name: "Choeradodis rhombicollis", | |
| commonName: "Mante feuille rhomboïde", | |
| taxonKey: "1405204", | |
| family: "Mantidae", | |
| region: "Amérique centrale et du Sud", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Amérique centrale et du Sud", | |
| "Mimétisme exceptionnel de feuille avec prothorax élargi en forme de bouclier" | |
| ] | |
| }, | |
| { | |
| name: "Choeradodis servillei", | |
| commonName: "Mante feuille de Serville", | |
| taxonKey: "1405196", | |
| family: "Mantidae", | |
| region: "Amérique du Sud", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Amérique du Sud tropicale", | |
| "Espèce arboricole imitant parfaitement une feuille verte" | |
| ] | |
| }, | |
| { | |
| name: "Rhombodera basalis", | |
| commonName: "Mante bouclier géante", | |
| taxonKey: "6725789", | |
| family: "Mantidae", | |
| region: "Asie du Sud-Est", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Asie du Sud-Est", | |
| "Grande mante robuste, très populaire en terrariophilie" | |
| ] | |
| }, | |
| { | |
| name: "Toxodera servillei", | |
| commonName: "Mante brindille", | |
| taxonKey: "1406838", | |
| family: "Toxoderidae", | |
| region: "Asie du Sud-Est", | |
| hints: [ | |
| "Famille : Toxoderidae", | |
| "Distribution : Asie du Sud-Est", | |
| "Apparence extrêmement élancée imitant une brindille" | |
| ] | |
| }, | |
| { | |
| name: "Prohierodula flavipennis", | |
| commonName: "Mante à ailes jaunes", | |
| taxonKey: "1406032", | |
| family: "Mantidae", | |
| region: "Asie du Sud-Est", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Asie du Sud-Est", | |
| "Ailes postérieures jaune vif, espèce de taille moyenne" | |
| ] | |
| }, | |
| { | |
| name: "Polyspilota aeruginosa", | |
| commonName: "Mante cuivrée", | |
| taxonKey: "1405481", | |
| family: "Mantidae", | |
| region: "Afrique subsaharienne", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Afrique subsaharienne", | |
| "Coloration vert-cuivré caractéristique, espèce robuste" | |
| ] | |
| }, | |
| { | |
| name: "Ameles spallanzania", | |
| commonName: "Amèle de Spallanzani", | |
| taxonKey: "5048707", | |
| family: "Amelidae", | |
| region: "Méditerranée", | |
| hints: [ | |
| "Famille : Amelidae", | |
| "Distribution : Bassin méditerranéen", | |
| "Petite mante, femelles souvent aptères (sans ailes fonctionnelles)" | |
| ] | |
| }, | |
| { | |
| name: "Ameles decolor", | |
| commonName: "Amèle décolorée", | |
| taxonKey: "5048690", | |
| family: "Amelidae", | |
| region: "Méditerranée", | |
| hints: [ | |
| "Famille : Amelidae", | |
| "Distribution : Europe du Sud et Afrique du Nord", | |
| "Petite espèce cryptique, coloration variable selon le substrat" | |
| ] | |
| }, | |
| { | |
| name: "Hierodula pulchripennis", | |
| commonName: "Mante à belles ailes", | |
| taxonKey: "1405884", | |
| family: "Mantidae", | |
| region: "Asie du Sud-Est", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Asie du Sud-Est", | |
| "Grande mante verte avec motifs délicats sur les ailes" | |
| ] | |
| }, | |
| { | |
| name: "Callibia diana", | |
| commonName: "Mante de Diana", | |
| taxonKey: "1404245", | |
| family: "Nanomantidae", | |
| region: "Afrique", | |
| hints: [ | |
| "Famille : Nanomantidae", | |
| "Distribution : Afrique tropicale", | |
| "Petite mante aux motifs contrastés noir et blanc" | |
| ] | |
| }, | |
| { | |
| name: "Brunneria borealis", | |
| commonName: "Mante-bâton", | |
| taxonKey: "5048768", | |
| family: "Mantidae", | |
| region: "Amérique du Nord", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Sud des États-Unis", | |
| "Corps extrêmement élancé, reproduction par parthénogenèse (pas de mâles)" | |
| ] | |
| }, | |
| { | |
| name: "Popa spurca", | |
| commonName: "Mante écorce africaine", | |
| taxonKey: "8821604", | |
| family: "Liturgusidae", | |
| region: "Afrique", | |
| hints: [ | |
| "Famille : Liturgusidae", | |
| "Distribution : Afrique subsaharienne", | |
| "Mimétisme d'écorce exceptionnel, corps aplati et rugueux" | |
| ] | |
| }, | |
| { | |
| name: "Pseudocreobotra wahlbergii", | |
| commonName: "Mante fleur épineuse", | |
| taxonKey: "1406642", | |
| family: "Hymenopodidae", | |
| region: "Afrique", | |
| hints: [ | |
| "Famille : Hymenopodidae", | |
| "Distribution : Afrique australe", | |
| "Motifs en spirale sur les ailes, abdomen en forme de feuille épineuse" | |
| ] | |
| }, | |
| { | |
| name: "Creobroter gemmatus", | |
| commonName: "Mante fleur indienne", | |
| taxonKey: "1406395", | |
| family: "Hymenopodidae", | |
| region: "Asie du Sud", | |
| hints: [ | |
| "Famille : Hymenopodidae", | |
| "Distribution : Inde, Asie du Sud", | |
| "Petite mante colorée avec taches oculaires vertes sur les ailes" | |
| ] | |
| }, | |
| { | |
| name: "Hymenopus coronatus", | |
| commonName: "Mante orchidée", | |
| taxonKey: "1406471", | |
| family: "Hymenopodidae", | |
| region: "Asie du Sud-Est", | |
| hints: [ | |
| "Famille : Hymenopodidae", | |
| "Distribution : Asie du Sud-Est (Malaisie, Indonésie)", | |
| "Célèbre pour son mimétisme d'orchidée, une des plus belles mantes au monde" | |
| ] | |
| }, | |
| { | |
| name: "Helvia cardinalis", | |
| commonName: "Mante cardinale", | |
| taxonKey: "5048799", | |
| family: "Hymenopodidae", | |
| region: "Amérique du Sud", | |
| hints: [ | |
| "Famille : Hymenopodidae", | |
| "Distribution : Amérique du Sud", | |
| "Coloration rouge distinctive, espèce rare en captivité" | |
| ] | |
| }, | |
| { | |
| name: "Tenodera sinensis", | |
| commonName: "Mante chinoise", | |
| taxonKey: "5887934", | |
| family: "Mantidae", | |
| region: "Asie, introduite Amérique du Nord", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Asie de l'Est, introduite en Amérique du Nord", | |
| "Une des plus grandes mantes, très robuste et vorace" | |
| ] | |
| }, | |
| { | |
| name: "Tenodera angustipennis", | |
| commonName: "Mante à ailes étroites", | |
| taxonKey: "4293587", | |
| family: "Mantidae", | |
| region: "Asie de l'Est", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Asie de l'Est (Japon, Chine, Corée)", | |
| "Grande mante proche de T. sinensis mais avec des ailes plus fines" | |
| ] | |
| }, | |
| { | |
| name: "Heterochaeta orientalis", | |
| commonName: "Mante orientale hétéroclite", | |
| taxonKey: "5048674", | |
| family: "Mantidae", | |
| region: "Afrique de l'Est", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Afrique de l'Est", | |
| "Espèce de taille moyenne avec coloration variable" | |
| ] | |
| }, | |
| { | |
| name: "Rhombodera kirbyi", | |
| commonName: "Mante bouclier de Kirby", | |
| taxonKey: "6725792", | |
| family: "Mantidae", | |
| region: "Asie du Sud-Est", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Asie du Sud-Est", | |
| "Grande mante similaire à R. basalis, très populaire en élevage" | |
| ] | |
| }, | |
| { | |
| name: "Orthodera ministralis", | |
| commonName: "Mante australienne du jardin", | |
| taxonKey: "1405115", | |
| family: "Mantidae", | |
| region: "Australie", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Australie", | |
| "Mante commune dans les jardins australiens, verte ou brune" | |
| ] | |
| }, | |
| { | |
| name: "Empusa pennata", | |
| commonName: "Empuse commune", | |
| taxonKey: "5048815", | |
| family: "Empusidae", | |
| region: "Méditerranée", | |
| hints: [ | |
| "Famille : Empusidae", | |
| "Distribution : Bassin méditerranéen", | |
| "Antennes plumeuses, silhouette très élancée avec crête sur la tête" | |
| ] | |
| }, | |
| { | |
| name: "Empusa fasciata", | |
| commonName: "Empuse fascié", | |
| taxonKey: "5048805", | |
| family: "Empusidae", | |
| region: "Méditerranée orientale", | |
| hints: [ | |
| "Famille : Empusidae", | |
| "Distribution : Méditerranée orientale, Moyen-Orient", | |
| "Proche d'E. pennata, corps élancé avec bandes caractéristiques" | |
| ] | |
| }, | |
| { | |
| name: "Sphodromantis lineola", | |
| commonName: "Mante africaine à ligne", | |
| taxonKey: "1404875", | |
| family: "Mantidae", | |
| region: "Afrique", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Afrique centrale et occidentale", | |
| "Grande mante verte avec bande blanche sur les ailes antérieures" | |
| ] | |
| }, | |
| { | |
| name: "Theopropus elegans", | |
| commonName: "Mante orchidée élégante", | |
| taxonKey: "1406531", | |
| family: "Hymenopodidae", | |
| region: "Asie du Sud-Est", | |
| hints: [ | |
| "Famille : Hymenopodidae", | |
| "Distribution : Asie du Sud-Est", | |
| "Lobes abdominaux en forme de pétales, mimétisme floral" | |
| ] | |
| }, | |
| { | |
| name: "Chlidonoptera lestoni", | |
| commonName: "Mante de Leston", | |
| taxonKey: "1406371", | |
| family: "Hymenopodidae", | |
| region: "Afrique", | |
| hints: [ | |
| "Famille : Hymenopodidae", | |
| "Distribution : Afrique centrale", | |
| "Espèce rare avec dimorphisme sexuel prononcé" | |
| ] | |
| }, | |
| { | |
| name: "Theopompa sp.", | |
| commonName: "Mante Theopompa", | |
| taxonKey: "1406967", | |
| family: "Hymenopodidae", | |
| region: "Asie", | |
| hints: [ | |
| "Famille : Hymenopodidae", | |
| "Distribution : Asie", | |
| "Genre avec plusieurs espèces difficiles à distinguer" | |
| ] | |
| }, | |
| { | |
| name: "Metallyticus splendidus", | |
| commonName: "Mante métallique", | |
| taxonKey: "1406791", | |
| family: "Metallyticidae", | |
| region: "Asie du Sud-Est", | |
| hints: [ | |
| "Famille : Metallyticidae", | |
| "Distribution : Asie du Sud-Est", | |
| "Petite mante aux reflets métalliques bleu-vert, aspect iridescent unique" | |
| ] | |
| }, | |
| { | |
| name: "Archimantis sp.", | |
| commonName: "Mante australienne", | |
| taxonKey: "5430805", | |
| family: "Mantidae", | |
| region: "Australie", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Australie", | |
| "Genre endémique australien de grandes mantes" | |
| ] | |
| }, | |
| { | |
| name: "Titanodula sp.", | |
| commonName: "Mante titan", | |
| taxonKey: "11149550", | |
| family: "Mantidae", | |
| region: "Asie", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Asie", | |
| "Grande mante du genre récemment décrit" | |
| ] | |
| }, | |
| { | |
| name: "Sibylla pretiosa", | |
| commonName: "Mante cryptique", | |
| taxonKey: "5048867", | |
| family: "Sibyllidae", | |
| region: "Afrique australe", | |
| hints: [ | |
| "Famille : Sibyllidae", | |
| "Distribution : Afrique australe", | |
| "Camouflage exceptionnel imitant écorce ou brindilles" | |
| ] | |
| }, | |
| { | |
| name: "Zoolea lobipes", | |
| commonName: "Mante à pattes lobées", | |
| taxonKey: "1404596", | |
| family: "Mantidae", | |
| region: "Afrique", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Afrique", | |
| "Pattes avec expansions en forme de lobes, espèce inhabituelle" | |
| ] | |
| }, | |
| { | |
| name: "Ceratocrania macra", | |
| commonName: "Mante à cornes", | |
| taxonKey: "1405086", | |
| family: "Nanomantidae", | |
| region: "Afrique", | |
| hints: [ | |
| "Famille : Nanomantidae", | |
| "Distribution : Afrique", | |
| "Petite mante avec protubérances en forme de cornes" | |
| ] | |
| }, | |
| { | |
| name: "Parablepharis kuhli", | |
| commonName: "Mante de Kuhl", | |
| taxonKey: "1406461", | |
| family: "Hymenopodidae", | |
| region: "Asie du Sud-Est", | |
| hints: [ | |
| "Famille : Hymenopodidae", | |
| "Distribution : Asie du Sud-Est", | |
| "Mimétisme de feuille, lobes foliaires sur les pattes" | |
| ] | |
| }, | |
| { | |
| name: "Phyllocrania paradoxa", | |
| commonName: "Mante feuille morte", | |
| taxonKey: "1406423", | |
| family: "Hymenopodidae", | |
| region: "Afrique", | |
| hints: [ | |
| "Famille : Hymenopodidae", | |
| "Distribution : Afrique subsaharienne (Madagascar)", | |
| "Mimétisme exceptionnel de feuille morte desséchée" | |
| ] | |
| }, | |
| { | |
| name: "Idolomorpha madagascariensis", | |
| commonName: "Mante de Madagascar", | |
| taxonKey: "1406706", | |
| family: "Empusidae", | |
| region: "Madagascar", | |
| hints: [ | |
| "Famille : Empusidae", | |
| "Distribution : Madagascar (endémique)", | |
| "Espèce élancée endémique de la Grande Île" | |
| ] | |
| }, | |
| { | |
| name: "Hierodula membranacea", | |
| commonName: "Mante asiatique géante", | |
| taxonKey: "1406012", | |
| family: "Mantidae", | |
| region: "Asie", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Asie du Sud et Sud-Est", | |
| "Grande mante verte très populaire en terrariophilie" | |
| ] | |
| }, | |
| { | |
| name: "Prohierodula picta", | |
| commonName: "Mante peinte", | |
| taxonKey: "1406039", | |
| family: "Mantidae", | |
| region: "Asie du Sud-Est", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Asie du Sud-Est", | |
| "Motifs colorés sur le corps, espèce de taille moyenne" | |
| ] | |
| }, | |
| { | |
| name: "Sphodromantis aurea", | |
| commonName: "Mante africaine dorée", | |
| taxonKey: "1404852", | |
| family: "Mantidae", | |
| region: "Afrique", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Afrique (Ghana principalement)", | |
| "Grande mante robuste, souvent avec taches dorées" | |
| ] | |
| }, | |
| { | |
| name: "Eremiaphila sp.", | |
| commonName: "Mante du désert", | |
| taxonKey: "1404075", | |
| family: "Eremiaphilidae", | |
| region: "Afrique du Nord, Moyen-Orient", | |
| hints: [ | |
| "Famille : Eremiaphilidae", | |
| "Distribution : Déserts d'Afrique du Nord et du Moyen-Orient", | |
| "Mantes terrestres adaptées aux environnements désertiques" | |
| ] | |
| }, | |
| { | |
| name: "Iris polystictica", | |
| commonName: "Mante Iris à points", | |
| taxonKey: "1404286", | |
| family: "Tarachodidae", | |
| region: "Méditerranée", | |
| hints: [ | |
| "Famille : Tarachodidae", | |
| "Distribution : Méditerranée orientale", | |
| "Proche d'I. oratoria, avec plusieurs ocelles sur les ailes" | |
| ] | |
| }, | |
| { | |
| name: "Rivetina baetica", | |
| commonName: "Mante ibérique", | |
| taxonKey: "7204677", | |
| family: "Rivetinidae", | |
| region: "Péninsule ibérique", | |
| hints: [ | |
| "Famille : Rivetinidae", | |
| "Distribution : Péninsule ibérique et Afrique du Nord", | |
| "Petite mante vivant au sol dans la végétation basse" | |
| ] | |
| }, | |
| { | |
| name: "Rivetina balcanica", | |
| commonName: "Mante balkanique", | |
| taxonKey: "4514096", | |
| family: "Rivetinidae", | |
| region: "Balkans", | |
| hints: [ | |
| "Famille : Rivetinidae", | |
| "Distribution : Péninsule balkanique", | |
| "Petite espèce discrète proche de R. baetica" | |
| ] | |
| }, | |
| { | |
| name: "Perlamantis allibertii", | |
| commonName: "Mante d'Allibert", | |
| taxonKey: "1403589", | |
| family: "Mantidae", | |
| region: "Afrique", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Afrique de l'Ouest", | |
| "Espèce de taille moyenne, peu commune en élevage" | |
| ] | |
| }, | |
| { | |
| name: "Macromantis ovalifolia", | |
| commonName: "Mante à feuilles ovales", | |
| taxonKey: "1405820", | |
| family: "Mantidae", | |
| region: "Amérique du Sud", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Amérique du Sud", | |
| "Grande mante aux ailes larges et ovales" | |
| ] | |
| }, | |
| { | |
| name: "Miomantis paykulli", | |
| commonName: "Mante égyptienne", | |
| taxonKey: "5048540", | |
| family: "Mantidae", | |
| region: "Afrique, introduite", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Afrique, introduite dans plusieurs régions", | |
| "Petite mante très adaptable, peut vivre en zones urbaines" | |
| ] | |
| }, | |
| { | |
| name: "Miomantis caffra", | |
| commonName: "Mante du Cap", | |
| taxonKey: "5048515", | |
| family: "Mantidae", | |
| region: "Afrique australe", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Afrique australe", | |
| "Petite mante commune en Afrique du Sud" | |
| ] | |
| }, | |
| { | |
| name: "Stagmomantis carolina", | |
| commonName: "Mante de Caroline", | |
| taxonKey: "1404940", | |
| family: "Mantidae", | |
| region: "Amérique du Nord", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : États-Unis (sud-est)", | |
| "Espèce commune aux États-Unis, très adaptable" | |
| ] | |
| }, | |
| { | |
| name: "Stagmomantis californica", | |
| commonName: "Mante de Californie", | |
| taxonKey: "1404928", | |
| family: "Mantidae", | |
| region: "Amérique du Nord", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Ouest des États-Unis (Californie)", | |
| "Espèce endémique de l'ouest américain" | |
| ] | |
| }, | |
| { | |
| name: "Paratoxodera sp.", | |
| commonName: "Mante brindille géante", | |
| taxonKey: "1406849", | |
| family: "Toxoderidae", | |
| region: "Asie du Sud-Est", | |
| hints: [ | |
| "Famille : Toxoderidae", | |
| "Distribution : Asie du Sud-Est", | |
| "Une des plus longues mantes au monde, apparence de brindille extrême" | |
| ] | |
| }, | |
| { | |
| name: "Mantis octospilota", | |
| commonName: "Mante à huit taches", | |
| taxonKey: "6258044", | |
| family: "Mantidae", | |
| region: "Europe du Sud", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Europe du Sud", | |
| "Proche de M. religiosa, avec taches caractéristiques" | |
| ] | |
| }, | |
| { | |
| name: "Tisma freyi", | |
| commonName: "Mante de Frey", | |
| taxonKey: "1404829", | |
| family: "Mantidae", | |
| region: "Amérique du Sud", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Amérique du Sud", | |
| "Espèce rare, peu documentée" | |
| ] | |
| }, | |
| { | |
| name: "Pnigomantis medioconstricta", | |
| commonName: "Mante à constriction", | |
| taxonKey: "1404986", | |
| family: "Mantidae", | |
| region: "Afrique", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Afrique", | |
| "Abdomen avec constriction médiane caractéristique" | |
| ] | |
| }, | |
| { | |
| name: "Tamolanica tamolana", | |
| commonName: "Mante de Tamolana", | |
| taxonKey: "1405781", | |
| family: "Mantidae", | |
| region: "Madagascar", | |
| hints: [ | |
| "Famille : Mantidae", | |
| "Distribution : Madagascar (endémique)", | |
| "Espèce endémique de Madagascar, peu connue" | |
| ] | |
| }, | |
| { | |
| name: "Deroplatys desiccata", | |
| commonName: "Mante feuille morte géante", | |
| taxonKey: "1405421", | |
| family: "Deroplatyidae", | |
| region: "Asie du Sud-Est", | |
| hints: [ | |
| "Famille : Deroplatyidae", | |
| "Distribution : Asie du Sud-Est", | |
| "Grande mante avec mimétisme de feuille morte, apparence très plate" | |
| ] | |
| } | |
| ]; | |
| // Update total species count | |
| document.getElementById('total-species').textContent = speciesData.length; | |
| // Game state | |
| let currentSpecies = null; | |
| let score = 0; | |
| let hintsRevealed = 0; | |
| let answered = false; | |
| let map = null; | |
| let tileLayer = null; | |
| let baseLayer = null; | |
| let selectedIndex = -1; | |
| let filteredSpecies = []; | |
| let currentMapType = 'standard'; | |
| // Map configurations | |
| const mapLayers = { | |
| standard: { | |
| url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', | |
| attribution: '© OpenStreetMap contributors' | |
| }, | |
| dark: { | |
| url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', | |
| attribution: '© OpenStreetMap contributors, © CARTO' | |
| }, | |
| satellite: { | |
| url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', | |
| attribution: 'Tiles © Esri' | |
| } | |
| }; | |
| // Initialize map | |
| function initMap() { | |
| map = L.map('map').setView([20, 0], 2); | |
| baseLayer = L.tileLayer(mapLayers.standard.url, { | |
| attribution: mapLayers.standard.attribution, | |
| maxZoom: 18 | |
| }).addTo(map); | |
| } | |
| // Change map type | |
| function changeMapType(type) { | |
| if (baseLayer) { | |
| map.removeLayer(baseLayer); | |
| } | |
| currentMapType = type; | |
| const config = mapLayers[type]; | |
| baseLayer = L.tileLayer(config.url, { | |
| attribution: config.attribution, | |
| maxZoom: 18 | |
| }).addTo(map); | |
| // Update active button | |
| document.querySelectorAll('.map-type-btn').forEach(btn => { | |
| btn.classList.toggle('active', btn.dataset.map === type); | |
| }); | |
| } | |
| // Add event listeners for map type buttons | |
| document.querySelectorAll('.map-type-btn').forEach(btn => { | |
| btn.addEventListener('click', () => { | |
| changeMapType(btn.dataset.map); | |
| }); | |
| }); | |
| // Load species occurrences on map | |
| function loadSpeciesOnMap(taxonKey) { | |
| if (tileLayer) { | |
| map.removeLayer(tileLayer); | |
| } | |
| tileLayer = L.tileLayer( | |
| `https://api.gbif.org/v2/map/occurrence/density/{z}/{x}/{y}@1x.png?taxonKey=${taxonKey}&bin=hex&hexPerTile=100&style=red.marker`, | |
| { | |
| attribution: '© GBIF', | |
| maxZoom: 18 | |
| } | |
| ); | |
| tileLayer.addTo(map); | |
| } | |
| // Autocomplete functionality | |
| const input = document.getElementById('species-input'); | |
| const dropdown = document.getElementById('autocomplete-dropdown'); | |
| function filterSpecies(query) { | |
| if (!query) return []; | |
| const lowerQuery = query.toLowerCase(); | |
| return speciesData.filter(species => | |
| species.name.toLowerCase().includes(lowerQuery) || | |
| species.commonName.toLowerCase().includes(lowerQuery) | |
| ).slice(0, 10); // Limit to 10 results | |
| } | |
| function showAutocomplete(species) { | |
| if (species.length === 0) { | |
| dropdown.style.display = 'none'; | |
| return; | |
| } | |
| filteredSpecies = species; | |
| dropdown.innerHTML = species.map((s, index) => ` | |
| <div class="autocomplete-item" data-index="${index}"> | |
| <strong>${s.commonName}</strong> | |
| <em>${s.name}</em> | |
| </div> | |
| `).join(''); | |
| dropdown.style.display = 'block'; | |
| selectedIndex = -1; | |
| } | |
| input.addEventListener('input', (e) => { | |
| const filtered = filterSpecies(e.target.value); | |
| showAutocomplete(filtered); | |
| }); | |
| input.addEventListener('keydown', (e) => { | |
| const items = dropdown.querySelectorAll('.autocomplete-item'); | |
| if (e.key === 'ArrowDown') { | |
| e.preventDefault(); | |
| selectedIndex = Math.min(selectedIndex + 1, items.length - 1); | |
| updateSelection(items); | |
| } else if (e.key === 'ArrowUp') { | |
| e.preventDefault(); | |
| selectedIndex = Math.max(selectedIndex - 1, 0); | |
| updateSelection(items); | |
| } else if (e.key === 'Enter') { | |
| e.preventDefault(); | |
| if (selectedIndex >= 0 && selectedIndex < filteredSpecies.length) { | |
| selectSpecies(filteredSpecies[selectedIndex]); | |
| } else { | |
| submitAnswer(); | |
| } | |
| } | |
| }); | |
| function updateSelection(items) { | |
| items.forEach((item, index) => { | |
| item.classList.toggle('selected', index === selectedIndex); | |
| }); | |
| if (selectedIndex >= 0) { | |
| items[selectedIndex].scrollIntoView({ block: 'nearest' }); | |
| } | |
| } | |
| dropdown.addEventListener('click', (e) => { | |
| const item = e.target.closest('.autocomplete-item'); | |
| if (item) { | |
| const index = parseInt(item.dataset.index); | |
| selectSpecies(filteredSpecies[index]); | |
| } | |
| }); | |
| function selectSpecies(species) { | |
| input.value = `${species.commonName} (${species.name})`; | |
| dropdown.style.display = 'none'; | |
| } | |
| document.addEventListener('click', (e) => { | |
| if (!input.contains(e.target) && !dropdown.contains(e.target)) { | |
| dropdown.style.display = 'none'; | |
| } | |
| }); | |
| // Start new round | |
| function startNewRound() { | |
| currentSpecies = speciesData[Math.floor(Math.random() * speciesData.length)]; | |
| hintsRevealed = 0; | |
| answered = false; | |
| loadSpeciesOnMap(currentSpecies.taxonKey); | |
| document.getElementById('hints-display').innerHTML = ''; | |
| document.getElementById('hint-btn').disabled = false; | |
| document.getElementById('result-container').innerHTML = ''; | |
| document.getElementById('species-input').value = ''; | |
| document.getElementById('species-input').disabled = false; | |
| document.getElementById('submit-btn').disabled = false; | |
| document.getElementById('next-btn').style.display = 'none'; | |
| input.focus(); | |
| } | |
| // Submit answer | |
| function submitAnswer() { | |
| if (answered || !input.value.trim()) return; | |
| answered = true; | |
| const userInput = input.value.toLowerCase(); | |
| const isCorrect = userInput.includes(currentSpecies.name.toLowerCase()) || | |
| userInput.includes(currentSpecies.commonName.toLowerCase()); | |
| document.getElementById('species-input').disabled = true; | |
| document.getElementById('submit-btn').disabled = true; | |
| if (isCorrect) { | |
| const points = Math.max(3 - hintsRevealed, 1); | |
| score += points; | |
| document.getElementById('score').textContent = score; | |
| document.getElementById('result-container').innerHTML = ` | |
| <div class="result-message correct"> | |
| ✓ Correct ! C'était bien ${currentSpecies.commonName}<br> | |
| <em>${currentSpecies.name}</em><br> | |
| +${points} point${points > 1 ? 's' : ''} | |
| </div> | |
| `; | |
| } else { | |
| document.getElementById('result-container').innerHTML = ` | |
| <div class="result-message incorrect"> | |
| ✗ Incorrect ! C'était ${currentSpecies.commonName}<br> | |
| <em>${currentSpecies.name}</em> | |
| </div> | |
| `; | |
| } | |
| document.getElementById('next-btn').style.display = 'block'; | |
| document.getElementById('hint-btn').disabled = true; | |
| } | |
| document.getElementById('submit-btn').addEventListener('click', submitAnswer); | |
| // Handle hint request | |
| document.getElementById('hint-btn').addEventListener('click', () => { | |
| if (hintsRevealed >= currentSpecies.hints.length || answered) return; | |
| const hint = currentSpecies.hints[hintsRevealed]; | |
| const hintElement = document.createElement('div'); | |
| hintElement.className = 'hint-item'; | |
| hintElement.innerHTML = ` | |
| <div class="hint-label">Indice ${hintsRevealed + 1} :</div> | |
| ${hint} | |
| `; | |
| document.getElementById('hints-display').appendChild(hintElement); | |
| hintsRevealed++; | |
| if (hintsRevealed >= currentSpecies.hints.length) { | |
| document.getElementById('hint-btn').disabled = true; | |
| document.getElementById('hint-btn').textContent = 'Tous les indices révélés'; | |
| } | |
| }); | |
| // Handle next round | |
| document.getElementById('next-btn').addEventListener('click', startNewRound); | |
| // Initialize game | |
| initMap(); | |
| startNewRound(); | |
| </script> | |
| </body> | |
| </html> |