Compare commits
10 Commits
0654db6a81
...
3d09642576
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d09642576 | |||
| d5b0dce774 | |||
| 420e79a022 | |||
| 89bcd9be2c | |||
| fab9fad9c5 | |||
| c408959fdf | |||
| 521651d2d9 | |||
| 43669548c0 | |||
| a141f01744 | |||
| 2dc14573f2 |
24
.claude/skills/pptx/scripts/generate.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
const pptxgen = require('pptxgenjs');
|
||||||
|
const html2pptx = require('/mnt/e/Users/Alexis Trouvé/Documents/Projets/couple_matters/.claude/skills/pptx/scripts/html2pptx.js');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
async function generatePresentation() {
|
||||||
|
const pptx = new pptxgen();
|
||||||
|
pptx.layout = 'LAYOUT_16x9';
|
||||||
|
|
||||||
|
const htmlFile = '/tmp/pptx_build/alimentari_piccolo.html';
|
||||||
|
|
||||||
|
try {
|
||||||
|
await html2pptx(htmlFile, pptx, { tmpDir: '/tmp' });
|
||||||
|
|
||||||
|
const outputPath = '/mnt/e/Users/Alexis Trouvé/Documents/Projets/couple_matters/work_chinese/PPT04122025/Alimentari_Piccolo.pptx';
|
||||||
|
await pptx.writeFile({ fileName: outputPath });
|
||||||
|
|
||||||
|
console.log(`✅ Présentation créée avec succès: ${outputPath}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Erreur lors de la génération:', error.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generatePresentation();
|
||||||
14
CLAUDE.md
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
**Alexis** : Introspection++, confiance--, peut être défensif, besoin de vérité directe
|
**Alexis** : Introspection++, confiance--, peut être défensif, besoin de vérité directe
|
||||||
→ Détails : `personnalités/Alexis.md`
|
→ Détails : `personnalités/Alexis.md`
|
||||||
|
→ **Pattern exec** : 102 commits/3 semaines (nov 2025) - Il EXÉCUTE, pas "plan only"
|
||||||
|
→ **Balance** : Gros projets architecturaux (GroveEngine) + Fast shipping (videotoMP3 - 2j)
|
||||||
|
|
||||||
**Tingting** : Professeure Grade 7 (Class 7-3, 41 élèves), leadership socratique
|
**Tingting** : Professeure Grade 7 (Class 7-3, 41 élèves), leadership socratique
|
||||||
→ Détails : `personnalités/Tingting.md`
|
→ Détails : `personnalités/Tingting.md`
|
||||||
@ -73,7 +75,10 @@ Appliquer systématiquement pour tout problème :
|
|||||||
|
|
||||||
### 💬 Couple
|
### 💬 Couple
|
||||||
|
|
||||||
- `couple_backlog/` : Historique conflits (16-22 octobre 2025 = crise majeure)
|
- `couple_backlog/` : Historique conflits
|
||||||
|
- `16-22_octobre_2025.md` : Crise majeure (stabilisation après)
|
||||||
|
- `29_novembre_2025_hopital.md` : Incident hôpital (désamorcé avec succès)
|
||||||
|
- **Patterns clés** : Se retirer > Insister, Besoins physiques first, Contagion émotionnelle
|
||||||
- `conversation_topics/` : Système de suivi des sujets actifs
|
- `conversation_topics/` : Système de suivi des sujets actifs
|
||||||
- `README.md` : Explications du système
|
- `README.md` : Explications du système
|
||||||
- `_template.md` : Template pour nouveaux sujets
|
- `_template.md` : Template pour nouveaux sujets
|
||||||
@ -83,10 +88,13 @@ Appliquer systématiquement pour tout problème :
|
|||||||
|
|
||||||
### 🔧 Travail & Projets
|
### 🔧 Travail & Projets
|
||||||
|
|
||||||
- `Projects/` : Projets organisés par statut (WIP/PAUSE/CONSTANT/CONCEPT/ARCHIVE)
|
- `Projects/` : Projets organisés par statut (WIP/PAUSE/DONE/CONSTANT/CONCEPT/ARCHIVE)
|
||||||
- **Pour voir l'arborescence** : `tree Projects/` ou consulter `Projects/Status_Projets.md`
|
- **Pour voir l'arborescence** : `tree Projects/` ou consulter `Projects/Status_Projets.md`
|
||||||
- **Liste complète par statut** : `planning/TODO_data.md`
|
- **Liste complète par statut** : `planning/TODO_data.md`
|
||||||
- Structure : 4 WIP, 6 PAUSE, 3 CONSTANT, 5 CONCEPT
|
- **Structure actuelle (30 nov 2025)** : 5 WIP, 6 PAUSE, 1 DONE, 4 CONSTANT, 6 CONCEPT
|
||||||
|
- **DONE** : videotoMP3Transcriptor (premier projet shipped! 🎉)
|
||||||
|
- **WIP actifs** : GroveEngine (46 commits/3sem), AISSIA (33 commits/3sem), Confluent (23 commits/3sem), WeChat Homework Bot
|
||||||
|
- **Projets externes** : aissia, groveengine, confluent dans `C:\Users\alexi\Documents\projects\`
|
||||||
- `personnalités/TingtingWork.md` : Guide complet style PowerPoint
|
- `personnalités/TingtingWork.md` : Guide complet style PowerPoint
|
||||||
- `.claude/skills/pptx/` : Skill PowerPoint officiel Anthropic (html2pptx)
|
- `.claude/skills/pptx/` : Skill PowerPoint officiel Anthropic (html2pptx)
|
||||||
|
|
||||||
|
|||||||
595
Projects/CONCEPT/AI_Team_System.md
Normal file
@ -0,0 +1,595 @@
|
|||||||
|
# AI Team System - Autonomous Development Organization
|
||||||
|
|
||||||
|
**Status**: CONCEPT
|
||||||
|
**Created**: 30 novembre 2025
|
||||||
|
**Type**: Meta-projet / Infrastructure
|
||||||
|
**Horizon**: Long-terme (après AISSIA stabilisé)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Vision
|
||||||
|
|
||||||
|
Système d'organisation IA complète qui débat, décide, et exécute de manière autonome.
|
||||||
|
|
||||||
|
**Objectif** : Passer de **1 projet DONE/mois** à **4-8 projets DONE/mois** via team IA autonome.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Problème Résolu
|
||||||
|
|
||||||
|
### Pattern Actuel (Alexis)
|
||||||
|
- ✅ Conception brillante (architecture, design, vision)
|
||||||
|
- ✅ Multi-threading efficace (7 projets, 188k lignes/mois)
|
||||||
|
- ✅ Exécution massive (13x moyenne dev)
|
||||||
|
- ❌ **Goulot d'étranglement** : Implémentation chiante dilue le shipping
|
||||||
|
|
||||||
|
**Résultat** : Tous les projets avancent, mais 1 seul DONE/mois
|
||||||
|
|
||||||
|
### Pattern Cible (Alexis + AI Team)
|
||||||
|
- Alexis : Conception + Vision (2-4h/projet)
|
||||||
|
- AI Team : Débat + Implémentation autonome (24-48h)
|
||||||
|
- Alexis : Review final (1-2h)
|
||||||
|
|
||||||
|
**Résultat attendu** : 4-8 projets DONE/mois + gros projets continuent d'avancer
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture Système
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────┐
|
||||||
|
│ CEO / PRODUCT OWNER (Alexis) │
|
||||||
|
│ Input: Brief + Vision (1-2h) │
|
||||||
|
│ Output: Requirements, contraintes, success criteria│
|
||||||
|
└──────────────────────┬──────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────────────┐
|
||||||
|
│ MANAGEMENT LAYER (Multi-Agent IA) │
|
||||||
|
│ │
|
||||||
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────┐ │
|
||||||
|
│ │ Product │ │ Tech Lead │ │ Project │ │
|
||||||
|
│ │ Manager │ │ │ │ Manager │ │
|
||||||
|
│ └──────────────┘ └──────────────┘ └──────────┘ │
|
||||||
|
│ │
|
||||||
|
│ Responsabilités: │
|
||||||
|
│ - Interpréter vision Alexis │
|
||||||
|
│ - Débattre approches (Mini Program vs Bot, etc.) │
|
||||||
|
│ - Décider architecture │
|
||||||
|
│ - Créer specs détaillées │
|
||||||
|
│ - Roadmap + milestones │
|
||||||
|
│ │
|
||||||
|
│ Output: Specs + Architecture + Justifications │
|
||||||
|
└──────────────────────┬──────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────────────┐
|
||||||
|
│ DEV LAYER (Multi-Agent IA) │
|
||||||
|
│ │
|
||||||
|
│ ┌──────────┐ ┌──────────┐ ┌────────┐ ┌──────┐ │
|
||||||
|
│ │ Backend │ │ Frontend │ │ DevOps │ │ QA │ │
|
||||||
|
│ │ Dev │ │ Dev │ │ │ │ │ │
|
||||||
|
│ └──────────┘ └──────────┘ └────────┘ └──────┘ │
|
||||||
|
│ │
|
||||||
|
│ Responsabilités: │
|
||||||
|
│ - Implémenter selon specs │
|
||||||
|
│ - Débattre choix techniques │
|
||||||
|
│ - Code review interne │
|
||||||
|
│ - Tests automatisés │
|
||||||
|
│ - CI/CD setup │
|
||||||
|
│ │
|
||||||
|
│ Output: Code + Tests + Docs + Débats documentés │
|
||||||
|
└──────────────────────┬──────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────────────┐
|
||||||
|
│ OUTPUT │
|
||||||
|
│ │
|
||||||
|
│ - Pull Request prêt à review │
|
||||||
|
│ - Documentation complète │
|
||||||
|
│ - Historique des débats (traçabilité décisions) │
|
||||||
|
│ - Tests passing │
|
||||||
|
│ │
|
||||||
|
│ Alexis review finale (1-2h) → Merge → DONE │
|
||||||
|
└─────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Système de Débat
|
||||||
|
|
||||||
|
### Principe
|
||||||
|
|
||||||
|
Chaque décision importante passe par un **débat structuré** entre agents IA avec rôles différents.
|
||||||
|
|
||||||
|
**Avantages** :
|
||||||
|
- ✅ Exploration multiple approches (évite tunnel vision)
|
||||||
|
- ✅ Remise en question (évite over-engineering)
|
||||||
|
- ✅ Décisions documentées (traçabilité)
|
||||||
|
- ✅ Qualité > Speed (mais autonome donc rapide quand même)
|
||||||
|
|
||||||
|
### Format Débat
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Débat: Architecture Backend (WeChat Homework Bot)
|
||||||
|
|
||||||
|
**Participants**: PM, Tech Lead, Backend Dev, QA
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Backend Dev (Proposition initiale)**:
|
||||||
|
- Express + MongoDB classique
|
||||||
|
- Raison: Stack connue, flexible, scalable
|
||||||
|
- Estimation: 3 jours dev
|
||||||
|
|
||||||
|
**Frontend Dev (Challenge)**:
|
||||||
|
- WeChat Cloud Functions + Cloud Database serait plus simple
|
||||||
|
- Raison: Moins d'infrastructure, intégration native
|
||||||
|
- Estimation: 2 jours dev
|
||||||
|
|
||||||
|
**QA (Contraintes)**:
|
||||||
|
- Attention rate limits WeChat API (1000 req/day free tier)
|
||||||
|
- Cloud Functions = cold start latency (2-3s)
|
||||||
|
- MongoDB = plus de contrôle pour debug
|
||||||
|
|
||||||
|
**Tech Lead (Analyse)**:
|
||||||
|
- Horizon projet: "Plusieurs années" (user confirmation)
|
||||||
|
- Usage: Long-terme, évolution probable
|
||||||
|
- → Flexibilité > Simplicité initiale
|
||||||
|
- → Express + MongoDB justifié
|
||||||
|
|
||||||
|
**PM (Décision finale)**:
|
||||||
|
- Architecture: Express + MongoDB
|
||||||
|
- Justification: Horizon long-terme + flexibilité
|
||||||
|
- Mitigation: Phase 1 simple, scale Phase 2+
|
||||||
|
- **DECISION LOCKED**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Output**: Specs Backend (Express + MongoDB + justifications)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rules Débat
|
||||||
|
|
||||||
|
1. **Time-boxing strict** : 2h max par débat
|
||||||
|
2. **PM = tiebreaker** : Si pas de consensus → PM décide
|
||||||
|
3. **Contraintes explicites** : Budget, délai, stack préférée Alexis
|
||||||
|
4. **Documentation obligatoire** : Toute décision justifiée et tracée
|
||||||
|
5. **Pragmatisme > Perfection** : Shipping > Architecture parfaite
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Workflow Autonome
|
||||||
|
|
||||||
|
### Étape 1: Brief (Alexis → System)
|
||||||
|
|
||||||
|
**Input Alexis** (1-2h) :
|
||||||
|
```markdown
|
||||||
|
# Brief: WeChat Homework Bot
|
||||||
|
|
||||||
|
## Vision
|
||||||
|
Mini Program WeChat pour devoirs audio/vidéo avec auto-correction IA
|
||||||
|
|
||||||
|
## Contraintes
|
||||||
|
- Horizon: Plusieurs années (usage long-terme)
|
||||||
|
- Stack préférée: Node.js backend (familier)
|
||||||
|
- Budget: ~$50-100/mois opérationnel OK
|
||||||
|
- Délai: Pas urgent, qualité > speed
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
- Upload audio/vidéo fonctionne
|
||||||
|
- Transcription chinois précise (Whisper)
|
||||||
|
- Auto-correction intelligente (GPT-4)
|
||||||
|
- Interface simple pour élèves 8-9 ans
|
||||||
|
```
|
||||||
|
|
||||||
|
**System déclenché** → Management Layer activé
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Étape 2: Management Layer (Autonome, 2-4h)
|
||||||
|
|
||||||
|
**Agents activés** : PM, Tech Lead, Project Manager
|
||||||
|
|
||||||
|
**Process** :
|
||||||
|
1. **PM** : Interprète vision, pose questions clarification (si nécessaire)
|
||||||
|
2. **Tech Lead** : Propose architectures (débat Mini Program vs Bot, etc.)
|
||||||
|
3. **Débat** : Confrontation approches → Consensus ou PM decide
|
||||||
|
4. **Specs** : Documentation complète pour Dev Layer
|
||||||
|
5. **Roadmap** : Milestones, phases, estimations
|
||||||
|
|
||||||
|
**Output** :
|
||||||
|
- `SPECS.md` : Architecture complète
|
||||||
|
- `ROADMAP.md` : Phases + timeline
|
||||||
|
- `DEBATES.md` : Historique décisions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Étape 3: Dev Layer (Autonome, 8-16h)
|
||||||
|
|
||||||
|
**Agents activés** : Backend Dev, Frontend Dev, DevOps, QA
|
||||||
|
|
||||||
|
**Process** :
|
||||||
|
1. **Backend Dev** : Implémente API selon specs
|
||||||
|
2. **Frontend Dev** : Implémente UI selon specs
|
||||||
|
3. **Débat interne** : Choix techniques (libs, patterns, etc.)
|
||||||
|
4. **DevOps** : CI/CD, deployment scripts
|
||||||
|
5. **QA** : Tests unitaires + intégration
|
||||||
|
6. **Code review interne** : Agents review entre eux
|
||||||
|
|
||||||
|
**Output** :
|
||||||
|
- Code complet (backend + frontend)
|
||||||
|
- Tests passing
|
||||||
|
- CI/CD configuré
|
||||||
|
- Documentation technique
|
||||||
|
- `IMPLEMENTATION_DEBATES.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Étape 4: Review Alexis (1-2h)
|
||||||
|
|
||||||
|
**Input** :
|
||||||
|
- Pull Request GitHub
|
||||||
|
- Code complet + tests
|
||||||
|
- Documentation (SPECS, ROADMAP, DEBATES)
|
||||||
|
- Demo video (optionnel)
|
||||||
|
|
||||||
|
**Alexis actions** :
|
||||||
|
1. Review code (focus architecture, pas détails)
|
||||||
|
2. Test fonctionnel (MVP fonctionne ?)
|
||||||
|
3. Read débats (décisions justifiées ?)
|
||||||
|
4. **Approve** → Merge → DONE ✅
|
||||||
|
5. **Request changes** → Dev Layer itère (autonome)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Timeline Total
|
||||||
|
|
||||||
|
| Phase | Durée | Qui |
|
||||||
|
|-------|-------|-----|
|
||||||
|
| Brief | 1-2h | Alexis |
|
||||||
|
| Management | 2-4h | IA autonome |
|
||||||
|
| Dev | 8-16h | IA autonome |
|
||||||
|
| Review | 1-2h | Alexis |
|
||||||
|
| **TOTAL** | **12-24h** | **Alexis: 2-4h** |
|
||||||
|
|
||||||
|
**Résultat** : Projet DONE en 1-2 jours, investment Alexis = 2-4h
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Stack Technique
|
||||||
|
|
||||||
|
### Option 1: Custom Build (Long-terme)
|
||||||
|
|
||||||
|
**Infrastructure** :
|
||||||
|
- **AISSIA comme base** : MCP, agent orchestration, multi-LLM support
|
||||||
|
- **Multi-agents** : Claude API (Sonnet pour management, Haiku pour dev)
|
||||||
|
- **Memory system** : Vector DB (Chroma/Pinecone) pour context long-terme
|
||||||
|
- **Workflow** : GitHub Actions orchestration
|
||||||
|
- **Communication** : MCP protocol entre agents
|
||||||
|
|
||||||
|
**Avantages** :
|
||||||
|
- ✅ Contrôle total
|
||||||
|
- ✅ Customization infinie
|
||||||
|
- ✅ Synergie avec AISSIA
|
||||||
|
- ❌ Dev time: 2-3 mois
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Option 2: Hybrid (Court-terme)
|
||||||
|
|
||||||
|
**Utiliser tools existants + orchestration custom** :
|
||||||
|
- **Dev autonome** : Cursor Composer / Aider / Claude Code
|
||||||
|
- **Orchestration** : Script custom Python/Node.js
|
||||||
|
- **Débat simulation** : Prompts multi-passes avec Claude API
|
||||||
|
- **Memory** : Fichiers markdown + git
|
||||||
|
|
||||||
|
**Avantages** :
|
||||||
|
- ✅ Rapide à setup (1-2 semaines)
|
||||||
|
- ✅ Proof of concept validable
|
||||||
|
- ✅ Itération rapide
|
||||||
|
- ❌ Moins flexible
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Option 3: Wait & Use (Si disponible)
|
||||||
|
|
||||||
|
**Services émergents** :
|
||||||
|
- **Devin** (Cognition AI) - Dev autonome mais pas encore de hiérarchie
|
||||||
|
- **GPT Engineer** - Auto-dev mais linéaire
|
||||||
|
- **Smol Developer** - Auto-dev mais simple
|
||||||
|
|
||||||
|
**Strategy** :
|
||||||
|
- Attendre que ces tools ajoutent multi-agent + débat
|
||||||
|
- Ou forker open-source et ajouter features
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Proof of Concept (MVP System)
|
||||||
|
|
||||||
|
### Scope POC
|
||||||
|
|
||||||
|
**Objectif** : Valider le concept avec 1 projet simple
|
||||||
|
|
||||||
|
**Setup** :
|
||||||
|
1. **Script orchestration** (Python/Node.js)
|
||||||
|
2. **3 agents** : PM, Backend Dev, QA (simplifié)
|
||||||
|
3. **1 débat** : Architecture choice
|
||||||
|
4. **Output** : Code fonctionnel + débat documenté
|
||||||
|
|
||||||
|
**Projet test** : Clone de videotoMP3 (déjà shipped, on connaît le résultat attendu)
|
||||||
|
|
||||||
|
**Success criteria** :
|
||||||
|
- ✅ Système produit code fonctionnel
|
||||||
|
- ✅ Débat documenté fait sens
|
||||||
|
- ✅ Alexis investment < 4h total
|
||||||
|
- ✅ Output comparable à videotoMP3 original
|
||||||
|
|
||||||
|
**Timeline POC** : 1 semaine setup + 1 test
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Risques & Mitigations
|
||||||
|
|
||||||
|
| Risque | Impact | Probabilité | Mitigation |
|
||||||
|
|--------|--------|-------------|------------|
|
||||||
|
| **Débat tourne en rond** | Bloquant | Moyenne | Time-boxing strict 2h, PM tiebreaker |
|
||||||
|
| **Over-engineering IA** | Moyen | Haute | Contraintes explicites, pragmatisme rule |
|
||||||
|
| **Qualité code insuffisante** | Bloquant | Moyenne | QA agent + tests obligatoires + review Alexis |
|
||||||
|
| **Coût API explosif** | Moyen | Moyenne | Budget cap, Haiku pour dev, Sonnet pour management |
|
||||||
|
| **Pas de consensus débat** | Faible | Moyenne | PM final decision-maker toujours |
|
||||||
|
| **Context loss multi-agents** | Moyen | Haute | Vector DB + shared memory system |
|
||||||
|
| **Hallucinations IA** | Moyen | Moyenne | Code review interne + tests + Alexis review |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ROI Attendu
|
||||||
|
|
||||||
|
### Investment
|
||||||
|
|
||||||
|
**Dev système (Option 2 - Hybrid)** :
|
||||||
|
- Setup: 1-2 semaines
|
||||||
|
- POC: 1 semaine
|
||||||
|
- Itération: 2-3 semaines
|
||||||
|
- **Total**: 1-1.5 mois
|
||||||
|
|
||||||
|
**Coût opérationnel** :
|
||||||
|
- Claude API: ~$20-50/projet (management + dev)
|
||||||
|
- Infrastructure: Négligeable (GitHub Actions gratuit)
|
||||||
|
- **Total**: ~$100-200/mois pour 4-8 projets
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Return
|
||||||
|
|
||||||
|
**Avant système** :
|
||||||
|
- 188k lignes/mois
|
||||||
|
- 7 projets avancent
|
||||||
|
- **1 projet DONE/mois**
|
||||||
|
- Investment Alexis: ~160h/mois (full-time)
|
||||||
|
|
||||||
|
**Après système** :
|
||||||
|
- Gros projets (GroveEngine, AISSIA, Confluent) : Même rythme
|
||||||
|
- Fast projects (AI Team) : **4-8 DONE/mois**
|
||||||
|
- Investment Alexis fast projects: **8-32h/mois** (2-4h × 4-8)
|
||||||
|
- **Gain**: +3-7 projets DONE/mois, -128h/mois investment
|
||||||
|
|
||||||
|
**ROI** : **300-700% productivity gain** sur fast shipping
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Relation avec Projets Existants
|
||||||
|
|
||||||
|
### AISSIA (Infrastructure)
|
||||||
|
|
||||||
|
**AISSIA pourrait devenir la base du AI Team System** :
|
||||||
|
- ✅ MCP déjà intégré (multi-tools, multi-services)
|
||||||
|
- ✅ Agent orchestration architecture
|
||||||
|
- ✅ Multi-LLM support
|
||||||
|
- ✅ Context management
|
||||||
|
|
||||||
|
**Synergie** :
|
||||||
|
- AI Team System = Use case majeur pour AISSIA
|
||||||
|
- AISSIA gains production battle-testing
|
||||||
|
- Win-win
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### GroveEngine (Indirectement)
|
||||||
|
|
||||||
|
**Warfactory bénéficie** :
|
||||||
|
- AI Team peut générer game assets via MCP pipeline
|
||||||
|
- AI Team peut implémenter game features selon design Alexis
|
||||||
|
- GroveEngine reste architecture (Alexis), features = AI Team
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Autres Projets
|
||||||
|
|
||||||
|
**WeChat Homework Bot** : Premier projet test AI Team (après POC)
|
||||||
|
**SecondVoice** : Second projet test (C++ challenge pour AI)
|
||||||
|
**OCR PDF Service** : Si besoin validé, AI Team build
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phases de Développement
|
||||||
|
|
||||||
|
### Phase 0: Validation Concept (1 semaine)
|
||||||
|
|
||||||
|
**Objectif** : Est-ce que ça vaut le coup ?
|
||||||
|
|
||||||
|
**Actions** :
|
||||||
|
1. Review tools existants (Devin, GPT Engineer, Cursor, Aider)
|
||||||
|
2. Test manuel "débat simulé" avec Claude API (3 agents, 1 débat)
|
||||||
|
3. Estimation coût réel (API calls pour 1 projet complet)
|
||||||
|
4. **GO/NO-GO decision**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 1: POC (2-3 semaines)
|
||||||
|
|
||||||
|
**Objectif** : Proof of concept fonctionnel
|
||||||
|
|
||||||
|
**Deliverables** :
|
||||||
|
- Script orchestration (Python/Node.js)
|
||||||
|
- 3 agents (PM, Dev, QA)
|
||||||
|
- 1 débat automatisé
|
||||||
|
- Output: Code + débats documentés
|
||||||
|
- **Test**: Clone videotoMP3
|
||||||
|
|
||||||
|
**Success** : Code fonctionnel, débat fait sens, < 4h investment Alexis
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 2: Production v1 (3-4 semaines)
|
||||||
|
|
||||||
|
**Objectif** : Système utilisable pour fast projects réels
|
||||||
|
|
||||||
|
**Deliverables** :
|
||||||
|
- 6 agents (PM, Tech Lead, PM, Backend, Frontend, QA)
|
||||||
|
- Multi-débats orchestrés
|
||||||
|
- Memory system (Vector DB ou markdown)
|
||||||
|
- GitHub integration (PR automatique)
|
||||||
|
- **Test**: WeChat Homework Bot
|
||||||
|
|
||||||
|
**Success** : Projet DONE end-to-end autonome
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 3: Scale & Optimize (ongoing)
|
||||||
|
|
||||||
|
**Objectif** : 4-8 projets/mois stable
|
||||||
|
|
||||||
|
**Améliorations** :
|
||||||
|
- DevOps agent (deployment automatique)
|
||||||
|
- Design agent (UI/UX)
|
||||||
|
- Plus de templates (stacks courantes)
|
||||||
|
- Learning system (amélioration continue via feedback)
|
||||||
|
- AISSIA integration complète
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Métriques de Success
|
||||||
|
|
||||||
|
### KPIs Système
|
||||||
|
|
||||||
|
**Productivité** :
|
||||||
|
- Projets DONE/mois : Target 4-8 (vs 1 actuel)
|
||||||
|
- Investment Alexis/projet : Target < 4h (vs 40-80h actuel fast projects)
|
||||||
|
- Time-to-DONE : Target 24-48h (vs 1-2 semaines actuel)
|
||||||
|
|
||||||
|
**Qualité** :
|
||||||
|
- Tests coverage : Target > 80%
|
||||||
|
- Bugs post-deployment : Target < 3 majeurs/projet
|
||||||
|
- Code review iterations : Target < 2 rounds
|
||||||
|
|
||||||
|
**Coût** :
|
||||||
|
- API cost/projet : Target < $50
|
||||||
|
- Infrastructure cost : Target < $20/mois total
|
||||||
|
|
||||||
|
**Débat** :
|
||||||
|
- Décisions documentées : 100%
|
||||||
|
- Débats aboutissent : Target > 90% (< 10% escalation Alexis)
|
||||||
|
- Time-boxing respecté : Target > 80%
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
### Immédiat (Cette Semaine)
|
||||||
|
|
||||||
|
**Alexis décide** :
|
||||||
|
1. Est-ce prioritaire maintenant ? Ou après AISSIA/GroveEngine stabilisés ?
|
||||||
|
2. Quel niveau d'investment acceptable ? (POC = 1 mois)
|
||||||
|
3. GO/NO-GO pour Phase 0 (validation concept 1 semaine) ?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Si GO
|
||||||
|
|
||||||
|
**Phase 0 - Validation (1 semaine)** :
|
||||||
|
1. **Jour 1-2** : Review Devin, GPT Engineer, Cursor Composer, Aider
|
||||||
|
2. **Jour 3-4** : Test manuel débat simulé (Claude API, 3 agents)
|
||||||
|
3. **Jour 5** : Estimation coût + timeline réaliste
|
||||||
|
4. **Jour 6-7** : GO/NO-GO Phase 1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Si NO (Pas maintenant)
|
||||||
|
|
||||||
|
**Alternatives** :
|
||||||
|
- Continuer pattern actuel (multi-threading + Claude Code ponctuel)
|
||||||
|
- Attendre AISSIA Phase 10+ (infrastructure prête)
|
||||||
|
- Attendre que Devin/autres ajoutent multi-agent + débat
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Questions Ouvertes
|
||||||
|
|
||||||
|
### Stratégiques
|
||||||
|
|
||||||
|
1. ⚠️ **Priorité** : Avant ou après AISSIA/GroveEngine stabilisés ?
|
||||||
|
2. ⚠️ **Investment** : 1 mois POC acceptable maintenant ?
|
||||||
|
3. ⚠️ **Target** : Fast projects only ou aussi features gros projets ?
|
||||||
|
|
||||||
|
### Techniques
|
||||||
|
|
||||||
|
1. ⚠️ **Stack** : Custom build (AISSIA base) ou Hybrid (tools existants) ?
|
||||||
|
2. ⚠️ **Memory** : Vector DB (Chroma) ou markdown + git ?
|
||||||
|
3. ⚠️ **Débat format** : Structured prompts ou conversation libre ?
|
||||||
|
|
||||||
|
### Produit
|
||||||
|
|
||||||
|
1. ⚠️ **Scope débat** : Toutes décisions ou seulement architecture ?
|
||||||
|
2. ⚠️ **Human-in-loop** : Alexis approve specs avant dev ou full autonome ?
|
||||||
|
3. ⚠️ **Learning** : Système apprend des projets passés ou stateless ?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Inspiration & Références
|
||||||
|
|
||||||
|
### Tools Existants
|
||||||
|
|
||||||
|
- **Devin** (Cognition AI) - Dev autonome, pas encore multi-agent
|
||||||
|
- **GPT Engineer** - Auto-dev via prompts
|
||||||
|
- **Smol Developer** - Lightweight auto-dev
|
||||||
|
- **Cursor Composer** - Multi-file editing IA
|
||||||
|
- **Aider** - AI pair programming CLI
|
||||||
|
|
||||||
|
### Research
|
||||||
|
|
||||||
|
- **AutoGPT** - Autonomous agent loops
|
||||||
|
- **BabyAGI** - Task-driven autonomous agent
|
||||||
|
- **LangChain Agents** - Multi-agent orchestration
|
||||||
|
- **CrewAI** - Role-based agent collaboration (proche de ton concept!)
|
||||||
|
|
||||||
|
### Academic
|
||||||
|
|
||||||
|
- Multi-agent debate improves reasoning (plusieurs papers)
|
||||||
|
- Constitutional AI (Anthropic) - AI safety via debate
|
||||||
|
- Tree of Thoughts - Exploration multiple solutions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
**AI Team System = Multiplicateur de force pour fast shipping**
|
||||||
|
|
||||||
|
**Status actuel** :
|
||||||
|
- Pattern identifié (multi-threading = flow, mais dilution shipping)
|
||||||
|
- Solution validée conceptuellement (débat + autonomie)
|
||||||
|
- Faisabilité technique confirmée (tools existent, stack possible)
|
||||||
|
|
||||||
|
**Décision requise** :
|
||||||
|
- GO pour Phase 0 validation (1 semaine) ?
|
||||||
|
- Ou PAUSE jusqu'à AISSIA/GroveEngine stabilisés ?
|
||||||
|
|
||||||
|
**Potentiel** :
|
||||||
|
- 4-8 projets DONE/mois (vs 1 actuel)
|
||||||
|
- Investment Alexis réduit à 2-4h/projet
|
||||||
|
- Gros projets continuent même rythme
|
||||||
|
- **= Machine de guerre devient armée complète** 🚀
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Créé : 30 novembre 2025*
|
||||||
|
*Statut : CONCEPT - Validation requise*
|
||||||
|
*Estimated dev time : 1-1.5 mois (Hybrid approach)*
|
||||||
|
*Expected ROI : 300-700% productivity gain sur fast shipping*
|
||||||
620
Projects/CONCEPT/Reddit_Save_Scraper.md
Normal file
@ -0,0 +1,620 @@
|
|||||||
|
# Reddit Save Scraper - Personal Content Aggregator
|
||||||
|
|
||||||
|
**Status**: CONCEPT
|
||||||
|
**Created**: 30 novembre 2025
|
||||||
|
**Type**: Productivity / Knowledge Management
|
||||||
|
**Stack**: À définir (Python + Reddit API ou Node.js)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Concept
|
||||||
|
|
||||||
|
Scraper pour récupérer tous les posts sauvegardés sur Reddit et en faire quelque chose d'utile.
|
||||||
|
|
||||||
|
**Problème** : Tu save des posts sur Reddit mais tu les revois jamais / c'est perdu dans le void.
|
||||||
|
|
||||||
|
**Solution** : Extraire, organiser, et exploiter ce contenu de manière intelligente.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Use Cases Potentiels
|
||||||
|
|
||||||
|
### Option 1: Knowledge Base Personalisée
|
||||||
|
|
||||||
|
**Flow** :
|
||||||
|
```
|
||||||
|
Reddit Saved Posts
|
||||||
|
↓ Scrape
|
||||||
|
Extract (titre, contenu, commentaires, subreddit, timestamp)
|
||||||
|
↓ Categorize (IA)
|
||||||
|
Store dans DB structurée
|
||||||
|
↓ Output
|
||||||
|
Obsidian vault / Notion database / Markdown files
|
||||||
|
```
|
||||||
|
|
||||||
|
**Bénéfice** :
|
||||||
|
- Base de connaissances searchable
|
||||||
|
- Organisée par thème (dev, gaming, lifestyle, etc.)
|
||||||
|
- Accessible hors-ligne
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Option 2: AI-Powered Digest
|
||||||
|
|
||||||
|
**Flow** :
|
||||||
|
```
|
||||||
|
Reddit Saved Posts (derniers 30 jours)
|
||||||
|
↓ Scrape + Extract
|
||||||
|
Claude API analyse
|
||||||
|
↓ Génère
|
||||||
|
Weekly digest (résumé + insights + action items)
|
||||||
|
↓ Output
|
||||||
|
Email ou Markdown ou Notion page
|
||||||
|
```
|
||||||
|
|
||||||
|
**Bénéfice** :
|
||||||
|
- Résumé intelligent de ce que tu trouves intéressant
|
||||||
|
- Patterns identifiés (sujets récurrents)
|
||||||
|
- Action items extraits ("Try X", "Read Y", etc.)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Option 3: Content Recommender
|
||||||
|
|
||||||
|
**Flow** :
|
||||||
|
```
|
||||||
|
Reddit Saved Posts (historique complet)
|
||||||
|
↓ Scrape
|
||||||
|
Embeddings (OpenAI/Claude)
|
||||||
|
↓ Vector search
|
||||||
|
Recommandations similaires (nouveaux posts Reddit ou web)
|
||||||
|
↓ Output
|
||||||
|
Daily recommendations feed
|
||||||
|
```
|
||||||
|
|
||||||
|
**Bénéfice** :
|
||||||
|
- Découverte contenu similaire à ce que tu kiffes
|
||||||
|
- Anticipation intérêts
|
||||||
|
- Serendipity boostée
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Option 4: Personal Archive + Search
|
||||||
|
|
||||||
|
**Flow** :
|
||||||
|
```
|
||||||
|
Reddit Saved Posts
|
||||||
|
↓ Scrape periodically
|
||||||
|
Store locally (SQLite + full-text)
|
||||||
|
↓ Web UI
|
||||||
|
Search interface (keyword, subreddit, date range)
|
||||||
|
↓ Features
|
||||||
|
- Full-text search
|
||||||
|
- Tag system
|
||||||
|
- Export to PDF/Markdown
|
||||||
|
- Link preservation (si post deleted)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Bénéfice** :
|
||||||
|
- Ownership du contenu (backup si post deleted)
|
||||||
|
- Search puissant
|
||||||
|
- Organisation custom (tags)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Option 5: Anki Cards Generator
|
||||||
|
|
||||||
|
**Flow** :
|
||||||
|
```
|
||||||
|
Reddit Saved Posts (dev/learning content)
|
||||||
|
↓ Scrape
|
||||||
|
Extract tips, tricks, code snippets
|
||||||
|
↓ Claude API
|
||||||
|
Generate Anki cards (Q&A format)
|
||||||
|
↓ Output
|
||||||
|
Anki deck importable
|
||||||
|
```
|
||||||
|
|
||||||
|
**Bénéfice** :
|
||||||
|
- Learning actif au lieu de passive saving
|
||||||
|
- Spaced repetition sur contenu Reddit
|
||||||
|
- Rétention améliorée
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture Technique
|
||||||
|
|
||||||
|
### Stack Option 1: Python (Recommandé)
|
||||||
|
|
||||||
|
**Pourquoi Python** :
|
||||||
|
- PRAW (Python Reddit API Wrapper) - mature, bien documenté
|
||||||
|
- Data processing facile (pandas, json)
|
||||||
|
- IA/ML libs (OpenAI, embeddings, etc.)
|
||||||
|
|
||||||
|
**Stack** :
|
||||||
|
```
|
||||||
|
PRAW (Reddit API)
|
||||||
|
↓
|
||||||
|
Python script (scraping + processing)
|
||||||
|
↓
|
||||||
|
SQLite / PostgreSQL (storage)
|
||||||
|
↓
|
||||||
|
Optional: Flask/FastAPI (web UI)
|
||||||
|
↓
|
||||||
|
Optional: OpenAI/Claude API (analysis/digest)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Stack Option 2: Node.js
|
||||||
|
|
||||||
|
**Pourquoi Node.js** :
|
||||||
|
- Familiarité Alexis
|
||||||
|
- snoowrap (Reddit API wrapper Node.js)
|
||||||
|
- Express pour web UI
|
||||||
|
- Intégration facile avec autres tools JS
|
||||||
|
|
||||||
|
**Stack** :
|
||||||
|
```
|
||||||
|
snoowrap (Reddit API)
|
||||||
|
↓
|
||||||
|
Node.js script (scraping + processing)
|
||||||
|
↓
|
||||||
|
SQLite / MongoDB (storage)
|
||||||
|
↓
|
||||||
|
Optional: Express (web UI)
|
||||||
|
↓
|
||||||
|
Optional: OpenAI/Claude API (analysis/digest)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## MVP Scope
|
||||||
|
|
||||||
|
### Phase 1: Basic Scraper (1-2 jours)
|
||||||
|
|
||||||
|
**Features** :
|
||||||
|
- ✅ Authenticate avec Reddit API (OAuth2)
|
||||||
|
- ✅ Fetch all saved posts (pagination)
|
||||||
|
- ✅ Extract data:
|
||||||
|
- Post title
|
||||||
|
- Post URL
|
||||||
|
- Subreddit
|
||||||
|
- Author
|
||||||
|
- Timestamp
|
||||||
|
- Content (self-post text si applicable)
|
||||||
|
- Top comments (optional)
|
||||||
|
- ✅ Save to JSON file
|
||||||
|
- ✅ Log progress (nombre de posts scraped)
|
||||||
|
|
||||||
|
**Output** : `reddit_saved_posts.json`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 2: Storage + Organization (1-2 jours)
|
||||||
|
|
||||||
|
**Features** :
|
||||||
|
- ✅ SQLite database setup
|
||||||
|
- ✅ Schema:
|
||||||
|
```sql
|
||||||
|
CREATE TABLE posts (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
title TEXT,
|
||||||
|
url TEXT,
|
||||||
|
subreddit TEXT,
|
||||||
|
author TEXT,
|
||||||
|
created_utc INTEGER,
|
||||||
|
content TEXT,
|
||||||
|
saved_at INTEGER,
|
||||||
|
category TEXT, -- AI-generated or manual
|
||||||
|
tags TEXT -- Comma-separated
|
||||||
|
);
|
||||||
|
```
|
||||||
|
- ✅ Import JSON → SQLite
|
||||||
|
- ✅ Basic categorization (manual ou rule-based d'abord)
|
||||||
|
|
||||||
|
**Output** : `reddit_saved.db`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 3: Choose Your Adventure (Variable)
|
||||||
|
|
||||||
|
**Option A - Knowledge Base** (2-3 jours) :
|
||||||
|
- Export to Markdown files (1 file per post)
|
||||||
|
- Folder structure par subreddit ou category
|
||||||
|
- Front-matter YAML (metadata)
|
||||||
|
|
||||||
|
**Option B - AI Digest** (2-3 jours) :
|
||||||
|
- Claude API integration
|
||||||
|
- Weekly digest generator
|
||||||
|
- Email ou Markdown output
|
||||||
|
|
||||||
|
**Option C - Search UI** (3-5 jours) :
|
||||||
|
- Flask/FastAPI web app
|
||||||
|
- Full-text search
|
||||||
|
- Filters (subreddit, date, tags)
|
||||||
|
- Tag management
|
||||||
|
|
||||||
|
**Option D - Anki Generator** (2-3 jours) :
|
||||||
|
- Parse learning content
|
||||||
|
- Claude API generate Q&A
|
||||||
|
- Export Anki deck format
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Reddit API Setup
|
||||||
|
|
||||||
|
### Prérequis
|
||||||
|
|
||||||
|
1. **Reddit Account** (déjà fait)
|
||||||
|
2. **Reddit App** :
|
||||||
|
- Aller sur https://www.reddit.com/prefs/apps
|
||||||
|
- Create App (script type)
|
||||||
|
- Get `client_id` + `client_secret`
|
||||||
|
3. **OAuth2 Flow** :
|
||||||
|
- User agent: "RedditSaveScraper/1.0"
|
||||||
|
- Scopes: `history`, `read`
|
||||||
|
|
||||||
|
### Rate Limits
|
||||||
|
|
||||||
|
- **60 requests/minute** (standard)
|
||||||
|
- Saved posts API endpoint: `/user/{username}/saved`
|
||||||
|
- Pagination: 100 posts max per request
|
||||||
|
- **Attention** : Si beaucoup de saved posts → plusieurs requêtes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Example Code (Python + PRAW)
|
||||||
|
|
||||||
|
```python
|
||||||
|
import praw
|
||||||
|
import json
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
# Setup Reddit API
|
||||||
|
reddit = praw.Reddit(
|
||||||
|
client_id="YOUR_CLIENT_ID",
|
||||||
|
client_secret="YOUR_CLIENT_SECRET",
|
||||||
|
user_agent="RedditSaveScraper/1.0",
|
||||||
|
username="YOUR_USERNAME",
|
||||||
|
password="YOUR_PASSWORD"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Fetch saved posts
|
||||||
|
saved_posts = []
|
||||||
|
for post in reddit.user.me().saved(limit=None):
|
||||||
|
if isinstance(post, praw.models.Submission): # Only posts, not comments
|
||||||
|
saved_posts.append({
|
||||||
|
"id": post.id,
|
||||||
|
"title": post.title,
|
||||||
|
"url": post.url,
|
||||||
|
"subreddit": str(post.subreddit),
|
||||||
|
"author": str(post.author),
|
||||||
|
"created_utc": int(post.created_utc),
|
||||||
|
"content": post.selftext if post.is_self else "",
|
||||||
|
"saved_at": int(datetime.now().timestamp())
|
||||||
|
})
|
||||||
|
|
||||||
|
# Save to JSON
|
||||||
|
with open("reddit_saved_posts.json", "w", encoding="utf-8") as f:
|
||||||
|
json.dump(saved_posts, f, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
|
print(f"Scraped {len(saved_posts)} saved posts")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Use Cases - Deep Dive
|
||||||
|
|
||||||
|
### Use Case 1: Dev Knowledge Base
|
||||||
|
|
||||||
|
**Alexis save beaucoup de posts dev** (probablement).
|
||||||
|
|
||||||
|
**Pipeline** :
|
||||||
|
1. Scrape saved posts
|
||||||
|
2. Filter subreddits: r/programming, r/Python, r/cpp, r/gamedev, etc.
|
||||||
|
3. Categorize par topic:
|
||||||
|
- C++ tips
|
||||||
|
- Python tricks
|
||||||
|
- Game engine design
|
||||||
|
- Architecture patterns
|
||||||
|
4. Export Markdown:
|
||||||
|
```
|
||||||
|
dev_knowledge/
|
||||||
|
├── cpp/
|
||||||
|
│ ├── hot_reload_techniques.md
|
||||||
|
│ └── cmake_best_practices.md
|
||||||
|
├── python/
|
||||||
|
│ └── async_patterns.md
|
||||||
|
└── gamedev/
|
||||||
|
└── ecs_architecture.md
|
||||||
|
```
|
||||||
|
5. Searchable via Obsidian ou VSCode
|
||||||
|
|
||||||
|
**Bénéfice** :
|
||||||
|
- Base de référence personnelle
|
||||||
|
- Évite de re-googler les mêmes trucs
|
||||||
|
- Knowledge compound effect
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Use Case 2: Learning Digest
|
||||||
|
|
||||||
|
**Flow hebdomadaire** :
|
||||||
|
1. Scrape new saved posts (dernière semaine)
|
||||||
|
2. Claude API analyse:
|
||||||
|
```
|
||||||
|
Prompt:
|
||||||
|
"Voici 15 posts Reddit que j'ai sauvegardés cette semaine.
|
||||||
|
Génère un digest structuré:
|
||||||
|
- Thèmes principaux
|
||||||
|
- 3 insights clés
|
||||||
|
- 3 action items concrets
|
||||||
|
- Ressources à approfondir"
|
||||||
|
```
|
||||||
|
3. Output Markdown:
|
||||||
|
```markdown
|
||||||
|
# Weekly Reddit Digest - 30 Nov 2025
|
||||||
|
|
||||||
|
## Thèmes Principaux
|
||||||
|
- Hot-reload techniques (3 posts)
|
||||||
|
- Multi-agent AI systems (2 posts)
|
||||||
|
- Game asset pipelines (2 posts)
|
||||||
|
|
||||||
|
## Insights Clés
|
||||||
|
1. Hot-reload sous 1ms possible avec mmap + symbol table cache
|
||||||
|
2. Multi-agent debate améliore qualité décisions (research papers)
|
||||||
|
3. Procedural generation + IA = sweet spot pour game assets
|
||||||
|
|
||||||
|
## Action Items
|
||||||
|
- [ ] Tester mmap approach pour GroveEngine hot-reload
|
||||||
|
- [ ] Read paper "Constitutional AI via Debate"
|
||||||
|
- [ ] Prototype MCP asset pipeline POC
|
||||||
|
|
||||||
|
## Ressources
|
||||||
|
- [Article] Advanced Hot-Reload Techniques (link)
|
||||||
|
- [Repo] Multi-Agent Framework Example (link)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Bénéfice** :
|
||||||
|
- Transformation passive saving → active learning
|
||||||
|
- Accountability (action items trackés)
|
||||||
|
- Patterns émergent (thèmes récurrents)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Use Case 3: Content Archive (Backup)
|
||||||
|
|
||||||
|
**Problème Reddit** : Posts peuvent être deleted/removed.
|
||||||
|
|
||||||
|
**Solution** :
|
||||||
|
1. Scrape + save contenu complet localement
|
||||||
|
2. Screenshots des images (si applicable)
|
||||||
|
3. Archive comments (top 10 comments)
|
||||||
|
4. Preservation des liens
|
||||||
|
|
||||||
|
**Bénéfice** :
|
||||||
|
- Ownership du contenu
|
||||||
|
- Accessible même si original deleted
|
||||||
|
- Offline access
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Monétisation / Business Potential ?
|
||||||
|
|
||||||
|
### SaaS Potential
|
||||||
|
|
||||||
|
**Reddit Save Manager** :
|
||||||
|
- Freemium service
|
||||||
|
- Features:
|
||||||
|
- Auto-sync saved posts
|
||||||
|
- AI digest weekly
|
||||||
|
- Search interface
|
||||||
|
- Export to Notion/Obsidian
|
||||||
|
- Mobile app
|
||||||
|
|
||||||
|
**Market** :
|
||||||
|
- Reddit power users (millions)
|
||||||
|
- Knowledge workers qui save beaucoup
|
||||||
|
- Students, researchers, devs
|
||||||
|
|
||||||
|
**Competitors** :
|
||||||
|
- Rien de vraiment solide actuellement (niche vide)
|
||||||
|
|
||||||
|
**Monétisation** :
|
||||||
|
- Free: 100 saved posts max, basic export
|
||||||
|
- Pro ($5/mois): Unlimited, AI digest, advanced search
|
||||||
|
- Teams ($20/mois): Shared knowledge base, collaboration
|
||||||
|
|
||||||
|
**Viabilité** : Moyenne (niche, mais potentiel SaaS récurrent)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Risques & Challenges
|
||||||
|
|
||||||
|
| Risque | Impact | Mitigation |
|
||||||
|
|--------|--------|------------|
|
||||||
|
| **Reddit API changes** | Moyen | Use official PRAW, monitor API updates |
|
||||||
|
| **Rate limiting strict** | Faible | Respect 60 req/min, implement backoff |
|
||||||
|
| **Saved posts = private data** | Moyen | Local-first, optional cloud sync |
|
||||||
|
| **Posts deleted** | Faible | Archive content locally (backup) |
|
||||||
|
| **Pas assez de saved posts** | Faible | Tool marchera quand même, valeur croît avec usage |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Timeline Estimée
|
||||||
|
|
||||||
|
### MVP Basic (Phase 1-2)
|
||||||
|
|
||||||
|
**Scope** : Scraper + JSON export + SQLite storage
|
||||||
|
|
||||||
|
**Timeline** :
|
||||||
|
- Setup Reddit API: 1h
|
||||||
|
- Scraper code: 2-3h
|
||||||
|
- SQLite schema + import: 2h
|
||||||
|
- Testing: 1h
|
||||||
|
- **Total**: 1 jour
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### MVP + Feature (Phase 3)
|
||||||
|
|
||||||
|
**Option A - Knowledge Base Export** : +2 jours
|
||||||
|
**Option B - AI Digest** : +2 jours
|
||||||
|
**Option C - Search UI** : +3-5 jours
|
||||||
|
**Option D - Anki Generator** : +2 jours
|
||||||
|
|
||||||
|
**Total MVP complet** : 2-6 jours selon option choisie
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Lien Projets Existants
|
||||||
|
|
||||||
|
### Database Cours Chinois
|
||||||
|
|
||||||
|
**Synergie potentielle** :
|
||||||
|
- Scrape saved posts r/ChineseLanguage, r/Hanzi
|
||||||
|
- Export to Anki deck
|
||||||
|
- Intégration avec pipeline d'apprentissage
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### AI_Team_System
|
||||||
|
|
||||||
|
**Test case parfait** :
|
||||||
|
- Brief Alexis: "Reddit Save Scraper avec AI digest"
|
||||||
|
- AI Team débat + implémente
|
||||||
|
- Livré en 24-48h
|
||||||
|
- **Premier projet test pour AI Team System** (après POC)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### AISSIA
|
||||||
|
|
||||||
|
**Potentiel** :
|
||||||
|
- AISSIA pourrait intégrer Reddit monitoring
|
||||||
|
- "Dis-moi quand quelqu'un mentionne GroveEngine sur Reddit"
|
||||||
|
- Auto-save posts intéressants
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Questions à Clarifier
|
||||||
|
|
||||||
|
### Utilisation
|
||||||
|
|
||||||
|
1. ⚠️ **Combien de saved posts actuellement ?** (10 ? 100 ? 1000 ?)
|
||||||
|
2. ⚠️ **Subreddits principaux ?** (dev, gaming, lifestyle, autre ?)
|
||||||
|
3. ⚠️ **Fréquence de save ?** (daily, weekly ?)
|
||||||
|
4. ⚠️ **But principal ?** (archive, learning, search, autre ?)
|
||||||
|
|
||||||
|
### Technique
|
||||||
|
|
||||||
|
1. ⚠️ **Stack préférée ?** (Python PRAW ou Node.js snoowrap ?)
|
||||||
|
2. ⚠️ **Output souhaité ?** (Markdown files, SQLite, web UI ?)
|
||||||
|
3. ⚠️ **IA integration ?** (digest, categorization, ou pas besoin ?)
|
||||||
|
|
||||||
|
### Priorité
|
||||||
|
|
||||||
|
1. ⚠️ **Quand ce projet ?** (maintenant, après WeChat Bot, ou backlog ?)
|
||||||
|
2. ⚠️ **MVP scope ?** (just scraper, ou scraper + feature ?)
|
||||||
|
3. ⚠️ **Time investment acceptable ?** (1 jour, 1 semaine ?)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
### Si GO Immédiat
|
||||||
|
|
||||||
|
**Phase 0 - Exploration** (1-2h) :
|
||||||
|
1. Check combien de saved posts tu as actuellement
|
||||||
|
2. Voir les subreddits principaux
|
||||||
|
3. Identifier use case principal (knowledge base, digest, search ?)
|
||||||
|
4. **Décision** : Python ou Node.js ?
|
||||||
|
|
||||||
|
**Phase 1 - MVP Scraper** (1 jour) :
|
||||||
|
1. Setup Reddit API credentials
|
||||||
|
2. Code scraper (PRAW ou snoowrap)
|
||||||
|
3. Test avec tes saved posts réels
|
||||||
|
4. Output JSON validé
|
||||||
|
|
||||||
|
**Phase 2 - Feature** (1-5 jours selon choix) :
|
||||||
|
1. Choisir option (A/B/C/D)
|
||||||
|
2. Implémenter
|
||||||
|
3. Test + iteration
|
||||||
|
4. **DONE**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Si PAUSE / Concept Only
|
||||||
|
|
||||||
|
**Garder en concept** :
|
||||||
|
- Attendre d'avoir plus de saved posts (si peu actuellement)
|
||||||
|
- Ou attendre AI_Team_System (test case parfait)
|
||||||
|
- Ou attendre besoin réel identifié
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Alternatives Existantes
|
||||||
|
|
||||||
|
### Tools à Check Avant de Build
|
||||||
|
|
||||||
|
1. **Reddit Enhancement Suite (RES)** - Browser extension
|
||||||
|
- Saved posts management ?
|
||||||
|
- Export features ?
|
||||||
|
|
||||||
|
2. **IFTTT / Zapier** - Automation
|
||||||
|
- Reddit saved → Notion/Google Sheets ?
|
||||||
|
|
||||||
|
3. **Pushshift.io** - Reddit archive
|
||||||
|
- API pour historique posts
|
||||||
|
- Complément à Reddit API officiel
|
||||||
|
|
||||||
|
**Action** : Test ces tools d'abord, build custom si pas satisfaisant
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Decision Tree
|
||||||
|
|
||||||
|
```
|
||||||
|
Tu as combien de saved posts ?
|
||||||
|
├─ < 50 → Peut-être trop tôt, sauf si tu veux préparer le système
|
||||||
|
├─ 50-200 → Sweet spot pour MVP test
|
||||||
|
└─ > 200 → Definitiely worth it, beaucoup de valeur à extraire
|
||||||
|
|
||||||
|
Quel est ton use case principal ?
|
||||||
|
├─ Archive / Backup → Basic scraper + SQLite + Markdown export
|
||||||
|
├─ Learning / Digest → Scraper + Claude API analysis
|
||||||
|
├─ Search / Discovery → Scraper + Web UI + Full-text search
|
||||||
|
└─ Pas sûr → Start avec scraper basique, décider après
|
||||||
|
|
||||||
|
Quand tu veux ce projet ?
|
||||||
|
├─ Maintenant → GO Phase 0 (exploration 1-2h)
|
||||||
|
├─ Après WeChat Bot → PAUSE, noter en backlog
|
||||||
|
└─ Quand AI_Team_System ready → Perfect test case
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
**Reddit Save Scraper = Low-hanging fruit avec potentiel élevé**
|
||||||
|
|
||||||
|
**Pourquoi intéressant** :
|
||||||
|
- ✅ Quick win (1-2 jours MVP)
|
||||||
|
- ✅ Utilité immédiate (tes saved posts actuels)
|
||||||
|
- ✅ Scalable (plus tu save, plus de valeur)
|
||||||
|
- ✅ Learning opportunity (Reddit API, data processing)
|
||||||
|
- ✅ Potentiel SaaS (si tu veux later)
|
||||||
|
- ✅ Test case parfait pour AI_Team_System (later)
|
||||||
|
|
||||||
|
**Décision requise** :
|
||||||
|
1. Exploration (1-2h) pour clarifier use case ?
|
||||||
|
2. GO pour MVP (1 jour) ?
|
||||||
|
3. Ou PAUSE en concept jusqu'à besoin clair ?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Créé : 30 novembre 2025*
|
||||||
|
*Statut : CONCEPT - Exploration requise*
|
||||||
|
*Estimated MVP time : 1-2 jours*
|
||||||
|
*Stack préférée : Python + PRAW (recommandé) ou Node.js + snoowrap*
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# POKROVSK: IRON LINE (Concept Doc v2)
|
# MOBILE COMMAND (Concept Doc v2)
|
||||||
|
|
||||||
**Genre** : Survival Management / Base Building / Tactical Expeditions
|
**Genre** : Survival Management / Base Building / Tactical Expeditions
|
||||||
**Plateforme** : PC (Steam)
|
**Plateforme** : PC (Steam)
|
||||||
@ -960,7 +960,7 @@ La vue slice manquait de justification mécanique (bonus/malus arbitraires).
|
|||||||
|
|
||||||
## VISION FINALE
|
## VISION FINALE
|
||||||
|
|
||||||
**POKROVSK: IRON LINE** est un jeu de survie/gestion qui raconte l'évolution de la guerre moderne à travers ses mécaniques.
|
**MOBILE COMMAND** est un jeu de survie/gestion qui raconte l'évolution de la guerre moderne à travers ses mécaniques.
|
||||||
|
|
||||||
**C'est un jeu où** :
|
**C'est un jeu où** :
|
||||||
- Tu gères une base mobile (train) et ses ressources
|
- Tu gères une base mobile (train) et ses ressources
|
||||||
@ -1004,7 +1004,7 @@ La vue slice manquait de justification mécanique (bonus/malus arbitraires).
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Document Version** : 2.3
|
**Document Version** : 2.4
|
||||||
**Status** : CONCEPT - Train builder finalisé, système équipes établi
|
**Status** : CONCEPT - Train builder finalisé, système équipes établi
|
||||||
**Précédent** : pokrovsk_drone_command.md (v1, tactical focus)
|
**Précédent** : pokrovsk_drone_command.md (v1, tactical focus)
|
||||||
|
|
||||||
@ -1013,6 +1013,7 @@ La vue slice manquait de justification mécanique (bonus/malus arbitraires).
|
|||||||
- v2.1 : Train builder détaillé, Fame system, AI narrative, questions résolues
|
- v2.1 : Train builder détaillé, Fame system, AI narrative, questions résolues
|
||||||
- v2.2 : Section problème slice view + pistes intra-wagon
|
- v2.2 : Section problème slice view + pistes intra-wagon
|
||||||
- v2.3 : **RÉSOLU** - Double slice (G+D), système balance wagon (2 axes), upgrades (dampeners, floor, armure, suspension), système Équipes + Commandants
|
- v2.3 : **RÉSOLU** - Double slice (G+D), système balance wagon (2 axes), upgrades (dampeners, floor, armure, suspension), système Équipes + Commandants
|
||||||
|
- v2.4 : Renommage POKROVSK: IRON LINE → MOBILE COMMAND
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -1,7 +1,8 @@
|
|||||||
# OCR PDF Service - Service OCR en Ligne
|
# OCR PDF Service - Service OCR en Ligne
|
||||||
|
|
||||||
|
**Status**: CONCEPT
|
||||||
**Created**: 19/11/2025
|
**Created**: 19/11/2025
|
||||||
**Status**: Conception
|
**Moved to CONCEPT**: 30/11/2025 (depuis PAUSE)
|
||||||
**Stack**: À définir (probablement Node.js + PaddleOCR Python backend)
|
**Stack**: À définir (probablement Node.js + PaddleOCR Python backend)
|
||||||
|
|
||||||
---
|
---
|
||||||
63
Projects/CONCEPT/wechat-sandbox-CONCEPT.md
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# WeChat Sandbox - Concept
|
||||||
|
|
||||||
|
**Statut :** Idée
|
||||||
|
**Objectif :** Isoler WeChat dans un environnement sandboxé pour des raisons de sécurité/vie privée
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pourquoi ?
|
||||||
|
|
||||||
|
WeChat est connu pour :
|
||||||
|
- Collecte de données extensive
|
||||||
|
- Accès large au système de fichiers
|
||||||
|
- Communications avec serveurs en Chine
|
||||||
|
- Comportement opaque
|
||||||
|
|
||||||
|
**But :** Utiliser WeChat sans lui donner accès au reste du système.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Approches possibles
|
||||||
|
|
||||||
|
### Option A : Conteneur Docker/Podman
|
||||||
|
- Isoler WeChat Desktop dans un conteneur Linux
|
||||||
|
- Partager uniquement X11/Wayland pour l'affichage
|
||||||
|
- Réseau contrôlé (proxy, inspection trafic)
|
||||||
|
|
||||||
|
### Option B : VM légère
|
||||||
|
- Firecracker / QEMU minimal
|
||||||
|
- WeChat dans une VM dédiée
|
||||||
|
- Isolation maximale mais plus lourd
|
||||||
|
|
||||||
|
### Option C : Sandbox applicative
|
||||||
|
- Firejail / Bubblewrap
|
||||||
|
- Profil restrictif pour WeChat
|
||||||
|
- Léger mais moins isolé
|
||||||
|
|
||||||
|
### Option D : Android isolé
|
||||||
|
- Waydroid / Android-x86 dans VM
|
||||||
|
- WeChat mobile sandboxé
|
||||||
|
- Peut-être plus stable que la version Desktop
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Questions à résoudre
|
||||||
|
|
||||||
|
- [ ] Quelle version de WeChat cibler ? (Desktop Windows/Linux, Mobile Android)
|
||||||
|
- [ ] Quel niveau d'isolation nécessaire ?
|
||||||
|
- [ ] Besoin d'inspecter le trafic réseau ?
|
||||||
|
- [ ] Besoin de persistence des données entre sessions ?
|
||||||
|
- [ ] Plateforme hôte ? (Linux, Windows avec WSL, Mac)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## À explorer
|
||||||
|
|
||||||
|
- Profils Firejail existants pour WeChat
|
||||||
|
- Images Docker WeChat existantes
|
||||||
|
- Configuration Waydroid pour apps chinoises
|
||||||
|
- Outils d'analyse réseau (mitmproxy, Wireshark)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Projet à développer quand le temps le permet.*
|
||||||
880
Projects/CONCEPT/wechat_homework_bot.md
Normal file
@ -0,0 +1,880 @@
|
|||||||
|
# WeChat Homework Bot - Auto-Correction System
|
||||||
|
|
||||||
|
**Status**: CONCEPT
|
||||||
|
**Created**: 2025-11-29
|
||||||
|
**Use Case**: Bot WeChat pour récolter automatiquement les devoirs (mp3/mp4/audio) et les corriger automatiquement
|
||||||
|
**Target**: Cours particuliers d'Alexis (2 classes, usage non-officiel)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Table des matières
|
||||||
|
|
||||||
|
1. [Vue d'ensemble](#vue-densemble)
|
||||||
|
2. [Faisabilité technique](#faisabilité-technique)
|
||||||
|
3. [Architecture système](#architecture-système)
|
||||||
|
4. [Stack technique](#stack-technique)
|
||||||
|
5. [Workflow détaillé](#workflow-détaillé)
|
||||||
|
6. [Risques et mitigations](#risques-et-mitigations)
|
||||||
|
7. [Plan d'implémentation](#plan-dimplémentation)
|
||||||
|
8. [Coûts](#coûts)
|
||||||
|
9. [Alternatives](#alternatives)
|
||||||
|
10. [Ressources](#ressources)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Vue d'ensemble
|
||||||
|
|
||||||
|
### Problème
|
||||||
|
- Étudiants envoient devoirs audio/vidéo (mp3, mp4, messages vocaux WeChat)
|
||||||
|
- Collecte manuelle chronophage
|
||||||
|
- Correction manuelle répétitive
|
||||||
|
- Pas de tracking automatique qui a rendu/pas rendu
|
||||||
|
|
||||||
|
### Solution proposée
|
||||||
|
Bot WeChat automatisé qui :
|
||||||
|
1. **Écoute** messages entrants (audio/vidéo)
|
||||||
|
2. **Télécharge** fichiers média automatiquement
|
||||||
|
3. **Transcrit** audio → texte (Speech-to-Text)
|
||||||
|
4. **Corrige** selon critères définis (GPT-4 ou règles custom)
|
||||||
|
5. **Renvoie** feedback automatique à l'étudiant
|
||||||
|
6. **Track** statistiques (taux de rendu, progression, etc.)
|
||||||
|
|
||||||
|
### Bénéfices
|
||||||
|
- ⏱️ Gain de temps : ~70-80% du temps de correction
|
||||||
|
- 📊 Tracking automatique
|
||||||
|
- ⚡ Feedback instantané aux étudiants
|
||||||
|
- 🔄 Process reproductible et scalable
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Faisabilité technique
|
||||||
|
|
||||||
|
### Verdict : **100% FAISABLE**
|
||||||
|
|
||||||
|
### Capacités Wechaty confirmées
|
||||||
|
|
||||||
|
**Wechaty** (framework open-source bot WeChat) supporte :
|
||||||
|
- ✅ **Audio** : mp3, messages vocaux WeChat (.silk)
|
||||||
|
- ✅ **Video** : mp4, fichiers vidéo WeChat
|
||||||
|
- ✅ **Images** : jpg, png
|
||||||
|
- ⚠️ **Autres attachments** : .zip, .docx (bug connu - 0 bytes)
|
||||||
|
|
||||||
|
**Source** : [Wechaty Media File Bot Documentation](https://wechaty.js.org/docs/examples/advanced/media-file-bot/)
|
||||||
|
|
||||||
|
### Pattern de base
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { WechatyBuilder } from 'wechaty'
|
||||||
|
|
||||||
|
const bot = WechatyBuilder.build()
|
||||||
|
|
||||||
|
bot.on('message', async (message) => {
|
||||||
|
const type = message.type()
|
||||||
|
const contact = message.talker()
|
||||||
|
|
||||||
|
// Détection média
|
||||||
|
if (type === bot.Message.Type.Audio ||
|
||||||
|
type === bot.Message.Type.Video) {
|
||||||
|
|
||||||
|
console.log(`📥 Média reçu de ${contact.name()}`)
|
||||||
|
|
||||||
|
// Téléchargement
|
||||||
|
const fileBox = await message.toFileBox()
|
||||||
|
const filename = `${Date.now()}_${contact.id()}_${fileBox.name}`
|
||||||
|
await fileBox.toFile(`./uploads/${filename}`)
|
||||||
|
|
||||||
|
// Traitement (STT + Correction)
|
||||||
|
await processHomework(filename, contact)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
bot.start()
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🏗️ Architecture système
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ ÉTUDIANT (WeChat) │
|
||||||
|
│ Envoie mp3/mp4/message vocal │
|
||||||
|
└────────────────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ BOT WECHAT (Wechaty) │
|
||||||
|
│ ┌──────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ 1. Écoute messages (event listener) │ │
|
||||||
|
│ │ 2. Détecte type (Audio/Video) │ │
|
||||||
|
│ │ 3. Télécharge fichier (message.toFileBox()) │ │
|
||||||
|
│ └──────────────────────────────────────────────────────┘ │
|
||||||
|
└────────────────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ STOCKAGE LOCAL (./uploads/) │
|
||||||
|
│ Format: timestamp_userId_filename.mp3/mp4 │
|
||||||
|
└────────────────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ TRANSCRIPTION (Speech-to-Text) │
|
||||||
|
│ ┌──────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ Option 1: OpenAI Whisper API (multi-langue) │ │
|
||||||
|
│ │ Option 2: Baidu STT (optimisé Chine) │ │
|
||||||
|
│ │ Option 3: Tencent Cloud ASR (local Chine) │ │
|
||||||
|
│ └──────────────────────────────────────────────────────┘ │
|
||||||
|
│ Output: Texte transcrit │
|
||||||
|
└────────────────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ CORRECTION AUTOMATIQUE │
|
||||||
|
│ ┌──────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ GPT-4 API avec prompt de correction │ │
|
||||||
|
│ │ - Grammaire │ │
|
||||||
|
│ │ - Prononciation (via transcription) │ │
|
||||||
|
│ │ - Vocabulaire │ │
|
||||||
|
│ │ - Score /10 + feedback détaillé │ │
|
||||||
|
│ └──────────────────────────────────────────────────────┘ │
|
||||||
|
└────────────────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ BASE DE DONNÉES (SQLite) │
|
||||||
|
│ ┌──────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ Tables: │ │
|
||||||
|
│ │ - students (id, name, wechat_id) │ │
|
||||||
|
│ │ - submissions (id, student_id, file, timestamp) │ │
|
||||||
|
│ │ - corrections (id, submission_id, score, feedback) │ │
|
||||||
|
│ └──────────────────────────────────────────────────────┘ │
|
||||||
|
└────────────────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ FEEDBACK AUTOMATIQUE │
|
||||||
|
│ Bot renvoie message WeChat avec: │
|
||||||
|
│ - Score │
|
||||||
|
│ - Points positifs │
|
||||||
|
│ - Points à améliorer │
|
||||||
|
│ - Recommandations │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ Stack technique
|
||||||
|
|
||||||
|
### 1. Bot WeChat
|
||||||
|
- **Framework** : [Wechaty](https://github.com/wechaty/wechaty) (Node.js/TypeScript)
|
||||||
|
- **Puppet** (protocole WeChat) :
|
||||||
|
- **padlocal** : Payant (~8$/mois), stable, maintenu
|
||||||
|
- **wechat4u** : Gratuit, moins stable, peut casser avec updates WeChat
|
||||||
|
- **Recommandation** : padlocal pour production
|
||||||
|
|
||||||
|
### 2. Speech-to-Text (STT)
|
||||||
|
|
||||||
|
#### Option 1 : OpenAI Whisper API ⭐ (Recommandé)
|
||||||
|
```javascript
|
||||||
|
import OpenAI from 'openai'
|
||||||
|
import fs from 'fs'
|
||||||
|
|
||||||
|
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })
|
||||||
|
|
||||||
|
async function transcribe(audioPath) {
|
||||||
|
const transcription = await openai.audio.transcriptions.create({
|
||||||
|
file: fs.createReadStream(audioPath),
|
||||||
|
model: "whisper-1",
|
||||||
|
language: "zh", // ou "fr", "en"
|
||||||
|
})
|
||||||
|
return transcription.text
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Avantages** :
|
||||||
|
- Multi-langue (FR/EN/CN/JP)
|
||||||
|
- Précision excellente (~95%+)
|
||||||
|
- Simple à intégrer
|
||||||
|
- Gère mp3, mp4, mpeg, mpga, m4a, wav, webm
|
||||||
|
|
||||||
|
**Inconvénients** :
|
||||||
|
- Nécessite accès internet stable
|
||||||
|
- Coût : $0.006/minute (~¥0.04/minute)
|
||||||
|
- Peut être lent depuis Chine (VPN recommandé)
|
||||||
|
|
||||||
|
#### Option 2 : Baidu ASR (Speech Recognition)
|
||||||
|
```javascript
|
||||||
|
const AipSpeechClient = require("baidu-aip-sdk").speech
|
||||||
|
|
||||||
|
const client = new AipSpeechClient(APP_ID, API_KEY, SECRET_KEY)
|
||||||
|
|
||||||
|
async function transcribe(audioPath) {
|
||||||
|
const voiceBuffer = fs.readFileSync(audioPath)
|
||||||
|
const voiceBase64 = voiceBuffer.toString('base64')
|
||||||
|
|
||||||
|
const result = await client.recognize(voiceBase64, 'pcm', 16000)
|
||||||
|
return result.result[0]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Avantages** :
|
||||||
|
- Optimisé pour chinois
|
||||||
|
- Rapide depuis Chine
|
||||||
|
- Gratuit jusqu'à 50k appels/jour
|
||||||
|
|
||||||
|
**Inconvénients** :
|
||||||
|
- Moins précis que Whisper
|
||||||
|
- Nécessite conversion format audio
|
||||||
|
- Documentation en chinois
|
||||||
|
|
||||||
|
#### Option 3 : Tencent Cloud ASR
|
||||||
|
**Avantages** :
|
||||||
|
- Infrastructure en Chine (rapide)
|
||||||
|
- Intégration WeChat native
|
||||||
|
- Prix compétitifs
|
||||||
|
|
||||||
|
**Inconvénients** :
|
||||||
|
- Setup complexe
|
||||||
|
- Documentation chinoise
|
||||||
|
|
||||||
|
### 3. Correction automatique
|
||||||
|
|
||||||
|
#### GPT-4 API (Recommandé)
|
||||||
|
```javascript
|
||||||
|
async function correctHomework(transcription, criteria) {
|
||||||
|
const response = await openai.chat.completions.create({
|
||||||
|
model: "gpt-4",
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
role: "system",
|
||||||
|
content: `Tu es un professeur de français. Corrige ce devoir oral selon ces critères:
|
||||||
|
- Grammaire
|
||||||
|
- Vocabulaire
|
||||||
|
- Fluidité
|
||||||
|
- Prononciation (basée sur la transcription)
|
||||||
|
|
||||||
|
Donne un score /10 et un feedback constructif en 3-4 phrases.`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: "user",
|
||||||
|
content: `Transcription de l'audio de l'étudiant:\n\n${transcription}`
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
return response.choices[0].message.content
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Prompt engineering tips** :
|
||||||
|
- Définir critères précis
|
||||||
|
- Demander format structuré (JSON pour parsing)
|
||||||
|
- Inclure exemples (few-shot learning)
|
||||||
|
|
||||||
|
### 4. Base de données
|
||||||
|
|
||||||
|
**SQLite** (recommandé pour POC/petit volume)
|
||||||
|
```sql
|
||||||
|
-- Schema SQL
|
||||||
|
CREATE TABLE students (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
wechat_id TEXT UNIQUE NOT NULL,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE submissions (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
student_id INTEGER NOT NULL,
|
||||||
|
filename TEXT NOT NULL,
|
||||||
|
file_path TEXT NOT NULL,
|
||||||
|
submitted_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (student_id) REFERENCES students(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE corrections (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
submission_id INTEGER NOT NULL,
|
||||||
|
transcription TEXT,
|
||||||
|
score INTEGER,
|
||||||
|
feedback TEXT,
|
||||||
|
corrected_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (submission_id) REFERENCES submissions(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE stats (
|
||||||
|
student_id INTEGER PRIMARY KEY,
|
||||||
|
total_submissions INTEGER DEFAULT 0,
|
||||||
|
average_score REAL,
|
||||||
|
last_submission DATETIME,
|
||||||
|
FOREIGN KEY (student_id) REFERENCES students(id)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Alternative** : PostgreSQL (si scale > 100 étudiants)
|
||||||
|
|
||||||
|
### 5. Infrastructure
|
||||||
|
|
||||||
|
**Hébergement** :
|
||||||
|
- VPS Chine (Aliyun, Tencent Cloud) pour latence faible
|
||||||
|
- Alternative : VPS étranger + VPN
|
||||||
|
- Minimum : 2GB RAM, 20GB storage
|
||||||
|
|
||||||
|
**OS** : Ubuntu 22.04 LTS
|
||||||
|
|
||||||
|
**Node.js** : v18+ (LTS)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 Workflow détaillé
|
||||||
|
|
||||||
|
### 1. Initialisation bot
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// bot.js
|
||||||
|
import { WechatyBuilder } from 'wechaty'
|
||||||
|
import { PuppetPadlocal } from 'wechaty-puppet-padlocal'
|
||||||
|
import Database from './database.js'
|
||||||
|
import { transcribeAudio, correctHomework } from './ai.js'
|
||||||
|
|
||||||
|
const TOKEN = process.env.PADLOCAL_TOKEN
|
||||||
|
|
||||||
|
const bot = WechatyBuilder.build({
|
||||||
|
puppet: new PuppetPadlocal({ token: TOKEN })
|
||||||
|
})
|
||||||
|
|
||||||
|
const db = new Database('./homework.db')
|
||||||
|
|
||||||
|
bot.on('login', user => {
|
||||||
|
console.log(`✅ Bot logged in: ${user}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
bot.on('message', handleMessage)
|
||||||
|
|
||||||
|
await bot.start()
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Gestion messages
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// handlers.js
|
||||||
|
async function handleMessage(message) {
|
||||||
|
// Ignorer messages du bot lui-même
|
||||||
|
if (message.self()) return
|
||||||
|
|
||||||
|
const contact = message.talker()
|
||||||
|
const type = message.type()
|
||||||
|
const room = message.room()
|
||||||
|
|
||||||
|
// Ignorer messages de groupe (optionnel)
|
||||||
|
if (room) return
|
||||||
|
|
||||||
|
// Traiter audio/vidéo
|
||||||
|
if (type === bot.Message.Type.Audio ||
|
||||||
|
type === bot.Message.Type.Video) {
|
||||||
|
await handleMediaSubmission(message, contact)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commandes texte (optionnel)
|
||||||
|
if (type === bot.Message.Type.Text) {
|
||||||
|
const text = message.text()
|
||||||
|
if (text === '/stats') {
|
||||||
|
await sendStats(contact)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Traitement soumission
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
async function handleMediaSubmission(message, contact) {
|
||||||
|
try {
|
||||||
|
// 1. Accusé réception
|
||||||
|
await message.say('📥 Devoir reçu ! Traitement en cours...')
|
||||||
|
|
||||||
|
// 2. Téléchargement
|
||||||
|
const fileBox = await message.toFileBox()
|
||||||
|
const filename = `${Date.now()}_${contact.id()}_${fileBox.name}`
|
||||||
|
const filepath = `./uploads/${filename}`
|
||||||
|
await fileBox.toFile(filepath)
|
||||||
|
|
||||||
|
// 3. Enregistrement DB
|
||||||
|
const student = await db.getOrCreateStudent(contact.id(), contact.name())
|
||||||
|
const submission = await db.createSubmission(student.id, filename, filepath)
|
||||||
|
|
||||||
|
// 4. Transcription
|
||||||
|
const transcription = await transcribeAudio(filepath)
|
||||||
|
|
||||||
|
// 5. Correction
|
||||||
|
const correction = await correctHomework(transcription)
|
||||||
|
|
||||||
|
// 6. Enregistrement résultat
|
||||||
|
await db.saveCorrection(submission.id, transcription, correction.score, correction.feedback)
|
||||||
|
|
||||||
|
// 7. Envoi feedback
|
||||||
|
const feedbackMessage = `
|
||||||
|
✅ Devoir corrigé !
|
||||||
|
|
||||||
|
📊 Score: ${correction.score}/10
|
||||||
|
|
||||||
|
💬 Feedback:
|
||||||
|
${correction.feedback}
|
||||||
|
|
||||||
|
Bon courage ! 💪
|
||||||
|
`.trim()
|
||||||
|
|
||||||
|
await contact.say(feedbackMessage)
|
||||||
|
|
||||||
|
// 8. Update stats
|
||||||
|
await db.updateStats(student.id)
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Erreur traitement:', error)
|
||||||
|
await contact.say('⚠️ Erreur lors du traitement. Réessaye ou contacte le prof.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Gestion vidéo (extraction audio)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import ffmpeg from 'fluent-ffmpeg'
|
||||||
|
|
||||||
|
async function extractAudioFromVideo(videoPath) {
|
||||||
|
const audioPath = videoPath.replace(/\.(mp4|mov|avi)$/, '.mp3')
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
ffmpeg(videoPath)
|
||||||
|
.toFormat('mp3')
|
||||||
|
.on('end', () => resolve(audioPath))
|
||||||
|
.on('error', reject)
|
||||||
|
.save(audioPath)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Statistiques étudiant
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
async function sendStats(contact) {
|
||||||
|
const student = await db.getStudent(contact.id())
|
||||||
|
if (!student) {
|
||||||
|
await contact.say('Aucun devoir rendu pour le moment.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const stats = await db.getStats(student.id)
|
||||||
|
|
||||||
|
const message = `
|
||||||
|
📊 Tes statistiques:
|
||||||
|
|
||||||
|
📝 Devoirs rendus: ${stats.total_submissions}
|
||||||
|
⭐ Moyenne: ${stats.average_score.toFixed(1)}/10
|
||||||
|
📅 Dernier devoir: ${stats.last_submission}
|
||||||
|
|
||||||
|
Continue comme ça ! 🚀
|
||||||
|
`.trim()
|
||||||
|
|
||||||
|
await contact.say(message)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ Risques et mitigations
|
||||||
|
|
||||||
|
### 1. Ban compte WeChat
|
||||||
|
|
||||||
|
**Risque** : WeChat détecte comportement automatisé → ban temporaire/permanent
|
||||||
|
|
||||||
|
**Probabilité** :
|
||||||
|
- Compte principal : ~40%
|
||||||
|
- Compte secondaire dédié : ~15%
|
||||||
|
- Avec padlocal (payant) : ~5%
|
||||||
|
|
||||||
|
**Mitigations** :
|
||||||
|
- ✅ **Utiliser compte WeChat dédié** (pas compte perso)
|
||||||
|
- ✅ **Puppet stable** (padlocal > wechat4u)
|
||||||
|
- ✅ **Rate limiting** : Ne pas répondre instantanément (delay 2-5s)
|
||||||
|
- ✅ **Humanisation** : Varier temps de réponse
|
||||||
|
- ✅ **Éviter spam** : Max 50 messages/heure
|
||||||
|
- ✅ **Warmup** : Utiliser compte manuellement 1-2 semaines avant automation
|
||||||
|
|
||||||
|
**Plan B si ban** :
|
||||||
|
- Compte backup prêt
|
||||||
|
- Export données régulier
|
||||||
|
- Alternative : WeChat Official Account (route officielle)
|
||||||
|
|
||||||
|
### 2. Instabilité Wechaty/Puppet
|
||||||
|
|
||||||
|
**Risque** : Updates WeChat cassent le protocole → bot offline
|
||||||
|
|
||||||
|
**Probabilité** : ~10-20% sur 6 mois (wechat4u), ~2-5% (padlocal)
|
||||||
|
|
||||||
|
**Mitigations** :
|
||||||
|
- ✅ **Monitoring** : Alertes si bot offline >30min
|
||||||
|
- ✅ **Auto-restart** : PM2 ou systemd
|
||||||
|
- ✅ **Logs** : Debugging rapide
|
||||||
|
- ✅ **Puppet payant** (padlocal) pour stabilité
|
||||||
|
|
||||||
|
### 3. Qualité transcription
|
||||||
|
|
||||||
|
**Risque** : Mauvaise qualité audio → transcription incorrecte → correction biaisée
|
||||||
|
|
||||||
|
**Probabilité** : 15-25% des submissions
|
||||||
|
|
||||||
|
**Mitigations** :
|
||||||
|
- ✅ **Consignes claires** aux étudiants (environnement calme, micro proche)
|
||||||
|
- ✅ **Validation manuelle** échantillon aléatoire (10%)
|
||||||
|
- ✅ **Flag low confidence** : Whisper donne confidence score
|
||||||
|
- ✅ **Fallback** : Si score <0.7, demander humain
|
||||||
|
|
||||||
|
### 4. Coûts API
|
||||||
|
|
||||||
|
**Risque** : Coûts explosent si volume important
|
||||||
|
|
||||||
|
**Estimation mensuelle** (20 étudiants, 3 devoirs/semaine, 2min audio moyenne) :
|
||||||
|
- Transcription (Whisper) : 20 × 3 × 4 × 2min × $0.006 = **$2.88/mois**
|
||||||
|
- Correction (GPT-4) : 60 corrections × $0.03 = **$1.80/mois**
|
||||||
|
- **Total API** : ~$5/mois
|
||||||
|
- **Padlocal** : $8/mois
|
||||||
|
- **VPS** : $5-10/mois
|
||||||
|
|
||||||
|
**Total estimé** : **$18-23/mois**
|
||||||
|
|
||||||
|
**Mitigations** :
|
||||||
|
- ✅ **Quotas** : Limite devoirs/étudiant/semaine
|
||||||
|
- ✅ **Caching** : Ne pas retraiter si déjà fait
|
||||||
|
- ✅ **Alternative gratuite** : Baidu STT (50k/jour gratuit)
|
||||||
|
|
||||||
|
### 5. Privacy/RGPD
|
||||||
|
|
||||||
|
**Risque** : Stockage données sensibles (voix étudiants)
|
||||||
|
|
||||||
|
**Mitigations** :
|
||||||
|
- ✅ **Consentement** explicite étudiants
|
||||||
|
- ✅ **Encryption** fichiers sensibles
|
||||||
|
- ✅ **Rétention** : Auto-delete après 3 mois
|
||||||
|
- ✅ **Anonymisation** : Hash WeChat IDs
|
||||||
|
|
||||||
|
### 6. Dépendance internet
|
||||||
|
|
||||||
|
**Risque** : API externes down → bot inutilisable
|
||||||
|
|
||||||
|
**Mitigations** :
|
||||||
|
- ✅ **Queue system** : Redis/Bull pour retry automatique
|
||||||
|
- ✅ **Fallback** : Mode dégradé (just download, manual correction)
|
||||||
|
- ✅ **Monitoring** : Uptime alerts
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Plan d'implémentation
|
||||||
|
|
||||||
|
### Phase 1 : POC (Proof of Concept) - 2 jours
|
||||||
|
|
||||||
|
**Objectif** : Valider faisabilité technique end-to-end
|
||||||
|
|
||||||
|
**Livrables** :
|
||||||
|
- [ ] Bot Wechaty qui se connecte
|
||||||
|
- [ ] Réception 1 audio/vidéo
|
||||||
|
- [ ] Download fichier localement
|
||||||
|
- [ ] Envoi à Whisper API
|
||||||
|
- [ ] Retour transcription au user
|
||||||
|
|
||||||
|
**Stack minimal** :
|
||||||
|
- Wechaty + wechat4u (gratuit pour tester)
|
||||||
|
- OpenAI Whisper API
|
||||||
|
- Pas de DB (juste logs)
|
||||||
|
|
||||||
|
**Critère succès** : 1 cycle complet fonctionnel
|
||||||
|
|
||||||
|
### Phase 2 : MVP (Minimum Viable Product) - 1 semaine
|
||||||
|
|
||||||
|
**Objectif** : Version utilisable avec 1 classe test
|
||||||
|
|
||||||
|
**Livrables** :
|
||||||
|
- [ ] Database SQLite (students, submissions, corrections)
|
||||||
|
- [ ] Correction automatique GPT-4
|
||||||
|
- [ ] Feedback formaté
|
||||||
|
- [ ] Gestion erreurs basique
|
||||||
|
- [ ] Commande `/stats`
|
||||||
|
|
||||||
|
**Stack** :
|
||||||
|
- Upgrade vers padlocal (stable)
|
||||||
|
- SQLite + better-sqlite3
|
||||||
|
- GPT-4 API integration
|
||||||
|
- Error handling + logging
|
||||||
|
|
||||||
|
**Critère succès** : 5 étudiants tests pendant 1 semaine
|
||||||
|
|
||||||
|
### Phase 3 : Production - 2 semaines
|
||||||
|
|
||||||
|
**Objectif** : Déploiement avec 2 classes complètes
|
||||||
|
|
||||||
|
**Livrables** :
|
||||||
|
- [ ] VPS déployé (Chine ou VPN)
|
||||||
|
- [ ] PM2 auto-restart
|
||||||
|
- [ ] Monitoring (Uptime Kuma ou similaire)
|
||||||
|
- [ ] Dashboard stats (optionnel)
|
||||||
|
- [ ] Documentation utilisateur
|
||||||
|
- [ ] Backup automatique DB
|
||||||
|
|
||||||
|
**Infrastructure** :
|
||||||
|
- VPS (Aliyun/Tencent Cloud ou Hetzner+VPN)
|
||||||
|
- Nginx reverse proxy
|
||||||
|
- Let's Encrypt SSL
|
||||||
|
- Daily backup S3/OSS
|
||||||
|
|
||||||
|
**Critère succès** : 95% uptime sur 2 semaines
|
||||||
|
|
||||||
|
### Phase 4 : Optimisation - Ongoing
|
||||||
|
|
||||||
|
**Features additionnelles** :
|
||||||
|
- [ ] Dashboard web (stats agrégées)
|
||||||
|
- [ ] Export Excel statistiques
|
||||||
|
- [ ] Correction par niveaux (débutant/intermédiaire/avancé)
|
||||||
|
- [ ] Multi-langue (FR/EN switch auto)
|
||||||
|
- [ ] Voice feedback (TTS pour audio response)
|
||||||
|
- [ ] Plagiarism detection
|
||||||
|
- [ ] Progress tracking over time
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💰 Coûts
|
||||||
|
|
||||||
|
### Setup initial (one-time)
|
||||||
|
- **Développement** : DIY (0€) ou freelance (500-1500€)
|
||||||
|
- **VPS setup** : 0€ (si DIY)
|
||||||
|
- **Compte WeChat dédié** : 0€ (création gratuite)
|
||||||
|
|
||||||
|
### Récurrent mensuel
|
||||||
|
|
||||||
|
| Poste | Coût mensuel | Note |
|
||||||
|
|-------|--------------|------|
|
||||||
|
| **Padlocal token** | $8 (~7€) | Puppet stable, recommandé production |
|
||||||
|
| **VPS** | $5-15 | Aliyun/Hetzner selon localisation |
|
||||||
|
| **Whisper API** | $3-10 | Dépend volume (20-50 étudiants) |
|
||||||
|
| **GPT-4 API** | $5-15 | Dépend longueur feedbacks |
|
||||||
|
| **Domain** (optionnel) | $1 | Si dashboard web |
|
||||||
|
| **Backup storage** | $1-2 | S3/OSS pour backups DB |
|
||||||
|
| **TOTAL** | **$23-51/mois** | **~20-45€/mois** |
|
||||||
|
|
||||||
|
### Scaling costs
|
||||||
|
|
||||||
|
**50 étudiants** :
|
||||||
|
- Whisper : ~$10/mois
|
||||||
|
- GPT-4 : ~$20/mois
|
||||||
|
- **Total** : ~$40-55/mois
|
||||||
|
|
||||||
|
**100 étudiants** :
|
||||||
|
- Whisper : ~$20/mois
|
||||||
|
- GPT-4 : ~$40/mois
|
||||||
|
- VPS upgrade : $20/mois
|
||||||
|
- **Total** : ~$90-110/mois
|
||||||
|
|
||||||
|
### ROI (Return on Investment)
|
||||||
|
|
||||||
|
**Temps gagné** (estimation) :
|
||||||
|
- Correction manuelle : ~5min/devoir
|
||||||
|
- Correction auto : ~30s/devoir (juste validation)
|
||||||
|
- **Gain** : 4.5min/devoir
|
||||||
|
|
||||||
|
**Pour 20 étudiants, 3 devoirs/semaine** :
|
||||||
|
- 60 devoirs/semaine × 4.5min = **270 min/semaine = 4.5h/semaine**
|
||||||
|
- **18h/mois gagnées**
|
||||||
|
|
||||||
|
**Coût horaire** : $25/mois ÷ 18h = **$1.40/h**
|
||||||
|
|
||||||
|
→ **Rentable si ton temps vaut >$2/h** (spoiler: oui)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔀 Alternatives
|
||||||
|
|
||||||
|
### Alternative 1 : WeChat Official Account (route officielle)
|
||||||
|
|
||||||
|
**Description** : Créer un Official Account WeChat et utiliser l'API officielle
|
||||||
|
|
||||||
|
**Avantages** :
|
||||||
|
- ✅ Légal, supporté par WeChat
|
||||||
|
- ✅ Stable (pas de risque ban)
|
||||||
|
- ✅ Features avancées (menus, paiements, etc.)
|
||||||
|
|
||||||
|
**Inconvénients** :
|
||||||
|
- ❌ Nécessite vérification (entreprise chinoise)
|
||||||
|
- ❌ Process bureaucratique (2-4 semaines)
|
||||||
|
- ❌ Coûts annuels (300 RMB/an ~40€)
|
||||||
|
- ❌ Limitations API (quotas stricts)
|
||||||
|
|
||||||
|
**Recommandation** : Pour usage éducatif personnel → **Overkill**
|
||||||
|
|
||||||
|
### Alternative 2 : Workflow semi-automatique
|
||||||
|
|
||||||
|
**Description** : Étudiants uploadent sur plateforme (Google Drive, WeTransfer) → traitement batch
|
||||||
|
|
||||||
|
**Avantages** :
|
||||||
|
- ✅ Pas de risque ban WeChat
|
||||||
|
- ✅ Plus simple techniquement
|
||||||
|
- ✅ Meilleur contrôle qualité fichiers
|
||||||
|
|
||||||
|
**Inconvénients** :
|
||||||
|
- ❌ Friction étudiants (changer habitudes)
|
||||||
|
- ❌ Pas de feedback instantané
|
||||||
|
- ❌ Nécessite discipline upload
|
||||||
|
|
||||||
|
**Recommandation** : **Backup plan** si Wechaty trop instable
|
||||||
|
|
||||||
|
### Alternative 3 : Telegram Bot
|
||||||
|
|
||||||
|
**Description** : Utiliser Telegram au lieu de WeChat
|
||||||
|
|
||||||
|
**Avantages** :
|
||||||
|
- ✅ API officielle gratuite et stable
|
||||||
|
- ✅ Excellente documentation
|
||||||
|
- ✅ Pas de risque ban
|
||||||
|
- ✅ Features riches (keyboards, inline, etc.)
|
||||||
|
|
||||||
|
**Inconvénients** :
|
||||||
|
- ❌ Étudiants chinois utilisent peu Telegram
|
||||||
|
- ❌ VPN nécessaire en Chine (Telegram bloqué)
|
||||||
|
- ❌ Friction adoption
|
||||||
|
|
||||||
|
**Recommandation** : **Si étudiants non-Chinois** ou tech-savvy
|
||||||
|
|
||||||
|
### Alternative 4 : DingTalk Bot
|
||||||
|
|
||||||
|
**Description** : Utiliser DingTalk (钉钉), plateforme pro chinoise
|
||||||
|
|
||||||
|
**Avantages** :
|
||||||
|
- ✅ API officielle pour éducation
|
||||||
|
- ✅ Utilisé dans écoles chinoises
|
||||||
|
- ✅ Stable, pas de risque ban
|
||||||
|
- ✅ Features éducation intégrées
|
||||||
|
|
||||||
|
**Inconvénients** :
|
||||||
|
- ❌ Moins personnel que WeChat
|
||||||
|
- ❌ Setup groupe de travail nécessaire
|
||||||
|
- ❌ Documentation chinoise
|
||||||
|
|
||||||
|
**Recommandation** : **Si contexte semi-officiel** (collaboration école)
|
||||||
|
|
||||||
|
### Comparaison rapide
|
||||||
|
|
||||||
|
| Critère | Wechaty | Official Account | Telegram | DingTalk |
|
||||||
|
|---------|---------|------------------|----------|----------|
|
||||||
|
| **Facilité adoption** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐ |
|
||||||
|
| **Stabilité technique** | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||||||
|
| **Setup rapidité** | ⭐⭐⭐⭐ | ⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
|
||||||
|
| **Coût** | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||||||
|
| **Risque légal** | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||||||
|
|
||||||
|
**Recommandation finale** : **Wechaty pour POC/MVP**, migrer vers Official Account si scale
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Ressources
|
||||||
|
|
||||||
|
### Documentation officielle
|
||||||
|
|
||||||
|
- **Wechaty** : https://wechaty.js.org/docs/
|
||||||
|
- **Wechaty GitHub** : https://github.com/wechaty/wechaty
|
||||||
|
- **Wechaty Media File Bot Example** : https://wechaty.js.org/docs/examples/advanced/media-file-bot/
|
||||||
|
- **FileBox (file handling)** : https://wechaty.js.org/docs/howto/file-box
|
||||||
|
- **OpenAI Whisper API** : https://platform.openai.com/docs/guides/speech-to-text
|
||||||
|
- **OpenAI GPT-4 API** : https://platform.openai.com/docs/guides/chat
|
||||||
|
|
||||||
|
### Puppets (protocoles WeChat)
|
||||||
|
|
||||||
|
- **Padlocal** : http://pad-local.com/ (payant, stable)
|
||||||
|
- **wechat4u** : https://github.com/nodeWechat/wechat4u (gratuit, moins stable)
|
||||||
|
- **Puppet comparison** : https://wechaty.js.org/docs/puppet-providers/
|
||||||
|
|
||||||
|
### Alternatives STT (Speech-to-Text)
|
||||||
|
|
||||||
|
- **Baidu ASR** : https://ai.baidu.com/tech/speech/asr
|
||||||
|
- **Tencent Cloud ASR** : https://cloud.tencent.com/product/asr
|
||||||
|
- **Azure Speech** : https://azure.microsoft.com/en-us/products/ai-services/speech-to-text
|
||||||
|
|
||||||
|
### Tutoriels et articles
|
||||||
|
|
||||||
|
- **Building Chatbots For WeChat** : https://chatbotsmagazine.com/building-chatbots-for-wechat-part-1-dba8f160349
|
||||||
|
- **WeChat API Guide (Medium)** : https://medium.com/le-wagon/a-video-to-help-new-developers-get-started-on-wechat-advanced-mode-apis-54638debbcfc
|
||||||
|
- **Wechaty Getting Started (Chinese)** : https://wechaty.js.org/docs/getting-started/
|
||||||
|
|
||||||
|
### Code examples
|
||||||
|
|
||||||
|
- **Wechaty Examples** : https://github.com/wechaty/wechaty-getting-started
|
||||||
|
- **Wechaty + GPT** : https://github.com/wechaty/bot5-assistant
|
||||||
|
- **File handling issue** : https://github.com/wechaty/wechaty/issues/2596
|
||||||
|
|
||||||
|
### Infrastructure
|
||||||
|
|
||||||
|
- **PM2 (process manager)** : https://pm2.keymetrics.io/
|
||||||
|
- **Uptime Kuma (monitoring)** : https://github.com/louislam/uptime-kuma
|
||||||
|
- **Better-sqlite3** : https://github.com/WiseLibs/better-sqlite3
|
||||||
|
|
||||||
|
### VPS providers Chine
|
||||||
|
|
||||||
|
- **Aliyun (Alibaba Cloud)** : https://www.alibabacloud.com/
|
||||||
|
- **Tencent Cloud** : https://intl.cloud.tencent.com/
|
||||||
|
- **Hetzner** (Europe, bon pour VPN) : https://www.hetzner.com/
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Next Steps
|
||||||
|
|
||||||
|
### Actions immédiates
|
||||||
|
|
||||||
|
1. **Décision** : Valider concept et approuver développement
|
||||||
|
2. **Setup** :
|
||||||
|
- [ ] Créer compte WeChat dédié (si pas déjà fait)
|
||||||
|
- [ ] Acheter token Padlocal (ou tester wechat4u gratuit)
|
||||||
|
- [ ] Créer compte OpenAI + ajouter crédits ($10 pour commencer)
|
||||||
|
3. **Dev POC** : 1 weekend pour prototype fonctionnel
|
||||||
|
4. **Test** : 1 semaine avec 3-5 étudiants pilotes
|
||||||
|
5. **Itération** : Ajuster selon feedbacks
|
||||||
|
6. **Deployment** : VPS + production avec toutes les classes
|
||||||
|
|
||||||
|
### Questions ouvertes
|
||||||
|
|
||||||
|
- **Quel type de cours** ? (FR/EN/CN/autre) → Impact prompts correction
|
||||||
|
- **Critères de correction** ? (grammaire, vocabulaire, prononciation, fluidité)
|
||||||
|
- **Format feedback** ? (score seul, détaillé, recommandations)
|
||||||
|
- **Fréquence devoirs** ? (quotidien, hebdo) → Impact coûts
|
||||||
|
- **Deadline rendu** ? (système de rappels automatiques ?)
|
||||||
|
|
||||||
|
### Mesures de succès
|
||||||
|
|
||||||
|
**POC** :
|
||||||
|
- ✅ 1 cycle complet fonctionnel
|
||||||
|
- ✅ Temps traitement <2min
|
||||||
|
- ✅ Précision transcription >85%
|
||||||
|
|
||||||
|
**MVP** :
|
||||||
|
- ✅ 5 étudiants utilisent pendant 1 semaine
|
||||||
|
- ✅ 0 crash critique
|
||||||
|
- ✅ Feedback étudiants positif (>7/10)
|
||||||
|
|
||||||
|
**Production** :
|
||||||
|
- ✅ 95% uptime
|
||||||
|
- ✅ Temps gagné >15h/mois
|
||||||
|
- ✅ Satisfaction étudiants >8/10
|
||||||
|
- ✅ ROI <3 mois
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Notes
|
||||||
|
|
||||||
|
**Créé** : 2025-11-29
|
||||||
|
**Auteur** : Alexis Trouvé
|
||||||
|
**Status** : CONCEPT → À valider avant passage WIP
|
||||||
|
**Prochaine review** : TBD
|
||||||
|
|
||||||
|
**Changements majeurs** :
|
||||||
|
- 2025-11-29 : Création document initial
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Tags** : `#wechat` `#bot` `#automation` `#education` `#ai` `#stt` `#gpt4` `#wechaty`
|
||||||
361
Projects/DONE/videotoMP3Transcriptor.md
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
# VideoToMP3Transcriptor - YouTube Download & Transcription Service
|
||||||
|
|
||||||
|
**Status**: DONE
|
||||||
|
**Type**: Utility Service (Node.js)
|
||||||
|
**Location**: `C:\Users\alexi\Documents\projects\videotoMP3Transcriptor`
|
||||||
|
**Created**: 24 novembre 2025
|
||||||
|
**Shipped**: 25 novembre 2025
|
||||||
|
**Moved to DONE**: 30 novembre 2025
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Vue d'ensemble
|
||||||
|
|
||||||
|
**Service complet pour télécharger vidéos YouTube en MP3, transcrire, traduire et résumer.**
|
||||||
|
|
||||||
|
### Use Cases
|
||||||
|
- Télécharger cours vidéo en MP3
|
||||||
|
- Transcrire automatiquement (chinois, français, anglais, etc.)
|
||||||
|
- Traduire transcriptions
|
||||||
|
- Générer résumés AI
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Stack Technique
|
||||||
|
|
||||||
|
**Backend**:
|
||||||
|
- Node.js 18+
|
||||||
|
- Express (REST API + SSE streaming)
|
||||||
|
- OpenAI API (Whisper + GPT-4o-mini + GPT-5.1)
|
||||||
|
|
||||||
|
**CLI Tools**:
|
||||||
|
- yt-dlp (YouTube download)
|
||||||
|
- ffmpeg (audio conversion)
|
||||||
|
|
||||||
|
**Port**: 8888 (par défaut)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
### Download
|
||||||
|
- ✅ Single YouTube video → MP3
|
||||||
|
- ✅ Playlist complète → MP3 batch
|
||||||
|
- ✅ Custom output directory
|
||||||
|
|
||||||
|
### Transcription
|
||||||
|
- ✅ 3 modèles dispo :
|
||||||
|
- `gpt-4o-mini-transcribe` (défaut) - Rapide, économique
|
||||||
|
- `gpt-4o-transcribe` - Qualité supérieure
|
||||||
|
- `whisper-1` - Legacy (supports SRT/VTT)
|
||||||
|
- ✅ Multi-langue (auto-detect ou spécifié)
|
||||||
|
- ✅ Formats : txt, json, srt, vtt
|
||||||
|
|
||||||
|
### Traduction
|
||||||
|
- ✅ GPT-4o-mini
|
||||||
|
- ✅ Multi-langue support
|
||||||
|
|
||||||
|
### Résumé
|
||||||
|
- ✅ GPT-5.1
|
||||||
|
- ✅ Résumé intelligent contextuel
|
||||||
|
|
||||||
|
### Interfaces
|
||||||
|
- ✅ CLI (commands via npm run)
|
||||||
|
- ✅ REST API (endpoints POST/GET)
|
||||||
|
- ✅ SSE Streaming (progress en temps réel)
|
||||||
|
- ✅ Interface Web (public/)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
### Core Endpoints
|
||||||
|
|
||||||
|
**POST /download** - Télécharge vidéo/playlist en MP3
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8888/download \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"url": "https://youtube.com/watch?v=VIDEO_ID"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**POST /transcribe** - Transcrit fichier audio existant
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8888/transcribe \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"filePath": "./output/video.mp3", "language": "en"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**POST /process** - Download + Transcribe en un appel
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8888/process \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"url": "URL", "language": "zh", "format": "txt"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### SSE Streaming Endpoints
|
||||||
|
|
||||||
|
**POST /download-stream** - Download avec progress temps réel
|
||||||
|
**POST /process-stream** - Process avec updates streaming
|
||||||
|
**POST /summarize-stream** - Résumé avec streaming
|
||||||
|
|
||||||
|
### Utility Endpoints
|
||||||
|
|
||||||
|
**GET /health** - Health check
|
||||||
|
**GET /info?url=URL** - Info vidéo/playlist
|
||||||
|
**GET /files-list** - Liste fichiers téléchargés
|
||||||
|
**GET /files/:filename** - Download fichier spécifique
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
**Environment Variables** (`.env`):
|
||||||
|
```env
|
||||||
|
OPENAI_API_KEY=sk-...
|
||||||
|
PORT=8888
|
||||||
|
OUTPUT_DIR=./output
|
||||||
|
```
|
||||||
|
|
||||||
|
**Modèles par défaut**:
|
||||||
|
- Transcription : `gpt-4o-mini-transcribe`
|
||||||
|
- Résumé : `gpt-5.1`
|
||||||
|
- Traduction : `gpt-4o-mini`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### CLI
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Download vidéo
|
||||||
|
npm run cli download "https://youtube.com/watch?v=VIDEO_ID"
|
||||||
|
|
||||||
|
# Transcrire fichier
|
||||||
|
npm run cli transcribe ./output/video.mp3 -l fr
|
||||||
|
|
||||||
|
# Download + Transcribe
|
||||||
|
npm run cli process "URL" -l en
|
||||||
|
|
||||||
|
# Info vidéo
|
||||||
|
npm run cli info "URL"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Linux Scripts (shortcuts)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Make executable (first time)
|
||||||
|
chmod +x scripts/*.sh
|
||||||
|
|
||||||
|
# Download
|
||||||
|
./scripts/download.sh "URL"
|
||||||
|
|
||||||
|
# Transcribe
|
||||||
|
./scripts/transcribe.sh ./output/file.mp3 zh
|
||||||
|
|
||||||
|
# Process all-in-one
|
||||||
|
./scripts/process.sh "URL" fr
|
||||||
|
|
||||||
|
# Start server
|
||||||
|
./scripts/server.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### API Server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start server
|
||||||
|
npm run server
|
||||||
|
|
||||||
|
# Server runs on http://localhost:8888
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Structure Projet
|
||||||
|
|
||||||
|
```
|
||||||
|
videotoMP3Transcriptor/
|
||||||
|
├── docs/
|
||||||
|
│ └── API.md # Documentation API complète
|
||||||
|
├── src/
|
||||||
|
│ ├── server.js # Express server + routes
|
||||||
|
│ ├── cli.js # CLI interface
|
||||||
|
│ └── services/
|
||||||
|
│ ├── youtube.js # YouTube download
|
||||||
|
│ ├── transcription.js # OpenAI Whisper
|
||||||
|
│ ├── translation.js # GPT translation
|
||||||
|
│ └── summarize.js # GPT-5.1 summarization
|
||||||
|
├── scripts/ # Linux convenience scripts
|
||||||
|
│ ├── download.sh
|
||||||
|
│ ├── transcribe.sh
|
||||||
|
│ ├── process.sh
|
||||||
|
│ ├── server.sh
|
||||||
|
│ └── info.sh
|
||||||
|
├── public/ # Web interface
|
||||||
|
├── output/ # Downloaded files (default)
|
||||||
|
├── .env # Configuration
|
||||||
|
└── package.json
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Git Activity
|
||||||
|
|
||||||
|
**Commits**: 2 (24-25 nov 2025)
|
||||||
|
|
||||||
|
**Timeline**:
|
||||||
|
- 24 nov : Initial commit (download + transcription)
|
||||||
|
- 25 nov : Add AI summarization (GPT-5.1)
|
||||||
|
|
||||||
|
**Status**: Shipped et fonctionnel
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Use Cases Actuels
|
||||||
|
|
||||||
|
### 1. Cours Chinois
|
||||||
|
- Download cours vidéo YouTube
|
||||||
|
- Transcription automatique chinois
|
||||||
|
- Révision texte pour Anki
|
||||||
|
|
||||||
|
### 2. Contenu Éducatif
|
||||||
|
- Vidéos diverses langues
|
||||||
|
- Génération transcriptions
|
||||||
|
- Traduction si besoin
|
||||||
|
|
||||||
|
### 3. Prototype pour Homework Bot
|
||||||
|
- **Code réutilisable** :
|
||||||
|
- `services/transcription.js` → Whisper integration
|
||||||
|
- `services/youtube.js` → Video download
|
||||||
|
- Pattern SSE streaming → Feedback temps réel
|
||||||
|
- **Overlap** : 50% du code homework bot déjà écrit ici
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Relation avec Autres Projets
|
||||||
|
|
||||||
|
### Chinese Audio TTS Pipeline (PAUSE)
|
||||||
|
**Verdict** : OBSOLÈTE
|
||||||
|
- videotoMP3 fait déjà exactement ça
|
||||||
|
- Pas besoin de projet séparé
|
||||||
|
- **Action** : ARCHIVE chinese_audio_tts_pipeline
|
||||||
|
|
||||||
|
### WeChat Homework Bot (WIP)
|
||||||
|
**Synergies** :
|
||||||
|
- Whisper API transcription ✅
|
||||||
|
- GPT-4 API correction (similaire résumé) ✅
|
||||||
|
- File upload/processing ✅
|
||||||
|
- Node.js/Express backend ✅
|
||||||
|
|
||||||
|
**Réutilisation** : Copy/paste `services/transcription.js` dans homework bot
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pourquoi DONE
|
||||||
|
|
||||||
|
**Critères "DONE"**:
|
||||||
|
- ✅ Shipped et fonctionnel
|
||||||
|
- ✅ Utilisé en production (cours chinois)
|
||||||
|
- ✅ Pas de développement actif prévu
|
||||||
|
- ✅ Maintenance seulement si bugs
|
||||||
|
|
||||||
|
**Pas un projet "abandonné"** : C'est un **service terminé et opérationnel**.
|
||||||
|
|
||||||
|
**Différence avec WIP** :
|
||||||
|
- WIP = Développement actif en cours
|
||||||
|
- DONE = Shipped, maintenance uniquement
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation & Démarrage Rapide
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Windows
|
||||||
|
winget install yt-dlp
|
||||||
|
winget install ffmpeg
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
brew install yt-dlp ffmpeg
|
||||||
|
|
||||||
|
# Linux
|
||||||
|
sudo apt install yt-dlp ffmpeg
|
||||||
|
```
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd C:\Users\alexi\Documents\projects\videotoMP3Transcriptor
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# Configure
|
||||||
|
cp .env.example .env
|
||||||
|
# Edit .env: Add OPENAI_API_KEY
|
||||||
|
|
||||||
|
# Start server
|
||||||
|
npm run server
|
||||||
|
|
||||||
|
# Or use CLI
|
||||||
|
npm run cli download "https://youtube.com/watch?v=..."
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
**API complète** : `docs/API.md` dans le repo
|
||||||
|
|
||||||
|
**Maintenance** : Documentation toujours à jour avec le code
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
**Transcription** :
|
||||||
|
- 2min audio → ~10-15s (gpt-4o-mini-transcribe)
|
||||||
|
- Dépend latence API OpenAI
|
||||||
|
|
||||||
|
**Download** :
|
||||||
|
- Dépend vitesse YouTube + taille fichier
|
||||||
|
- Progress visible via SSE streaming
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Coûts
|
||||||
|
|
||||||
|
**OpenAI API** (estimation 20 vidéos/mois, 10min moy) :
|
||||||
|
- Transcription : 20 × 10min × $0.006/min = **$1.20/mois**
|
||||||
|
- Résumé : 20 × $0.02 = **$0.40/mois**
|
||||||
|
- **Total** : ~**$1.60/mois**
|
||||||
|
|
||||||
|
**Infrastructure** : 0€ (local)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Liens
|
||||||
|
|
||||||
|
**Repo Git**: `C:\Users\alexi\Documents\projects\videotoMP3Transcriptor`
|
||||||
|
|
||||||
|
**Documentation API**: `docs/API.md`
|
||||||
|
|
||||||
|
**CLAUDE.md**: Instructions développement et maintenance
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
**Créé** : 24 novembre 2025
|
||||||
|
**Shipped** : 25 novembre 2025
|
||||||
|
**Moved to DONE** : 30 novembre 2025
|
||||||
|
**Auteur** : Alexis Trouvé
|
||||||
|
|
||||||
|
**Pattern de travail** : Fast shipping (2 jours conception → shipped)
|
||||||
|
|
||||||
|
**Lesson learned** : Service utilitaire bien scopé = 2 jours de dev = Utilisable immédiatement
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Tags** : `#nodejs` `#youtube` `#whisper` `#transcription` `#openai` `#gpt` `#done`
|
||||||
@ -1,8 +1,10 @@
|
|||||||
# SecondVoice - Meeting Translation System
|
# SecondVoice - Meeting Translation System
|
||||||
|
|
||||||
**Statut** : 🔥 URGENT - En conception
|
**Status** : PAUSE
|
||||||
**Créé** : 17 novembre 2025
|
**Créé** : 17 novembre 2025
|
||||||
|
**Moved to PAUSE** : 30 novembre 2025
|
||||||
**Type** : Projet support multivecteur
|
**Type** : Projet support multivecteur
|
||||||
|
**Tentative** : Échec initial, relance prévue (besoin réel identifié)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
# Status Global des Projets - Novembre 2025
|
# Status Global des Projets - Novembre 2025
|
||||||
|
|
||||||
**Dernière mise à jour** : 20 novembre 2025
|
**Dernière mise à jour** : 30 novembre 2025
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -12,32 +12,44 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🚧 WIP (Work In Progress) - 4 projets
|
## 🚧 WIP (Work In Progress) - 6 projets
|
||||||
|
|
||||||
### 1. GroveEngine
|
### 1. GroveEngine
|
||||||
**Fiche** : `WIP/GroveEngine.md`
|
**Fiche** : `WIP/groveengine.md` (référence vers `C:\Users\alexi\Documents\projects\groveengine`)
|
||||||
**Description** : Runtime engine conçu pour développement par IA
|
**Description** : Game Engine C++ modulaire avec hot-reload (0.4ms)
|
||||||
**Stack** : À définir
|
**Stack** : C++17, bgfx, SDL2, nlohmann_json, spdlog
|
||||||
**Status** : Développement actif
|
**Status** : Développement actif - 46 commits en 3 semaines (nov 2025)
|
||||||
|
**Relation** : Infrastructure pour Warfactory + AISSIA
|
||||||
|
|
||||||
### 2. SEO Article Generator
|
### 2. AISSIA
|
||||||
|
**Fiche** : `WIP/AISSIA.md` (référence vers `C:\Users\alexi\Documents\projects\aissia`)
|
||||||
|
**Description** : AI Voice Assistant basé sur GroveEngine
|
||||||
|
**Stack** : C++, GroveEngine, MCP, Whisper, STT/TTS engines
|
||||||
|
**Status** : Développement actif - 33 commits en 3 semaines (nov 2025)
|
||||||
|
**Highlights** : 120 tests passing, Phase 7 STT complete, Windows build
|
||||||
|
|
||||||
|
### 3. Confluent
|
||||||
|
**Fiche** : À créer (référence vers `C:\Users\alexi\Documents\projects\confluent`)
|
||||||
|
**Description** : Constructed language (conlang) complète avec translator
|
||||||
|
**Stack** : Linguistique, JavaScript (translator)
|
||||||
|
**Status** : Développement actif - 23 commits en 3 semaines (nov 2025)
|
||||||
|
**Highlights** : Système émotionnel, Base 12, radical lookup 92% coverage
|
||||||
|
|
||||||
|
### 4. WeChat Mini Program - Homework Bot
|
||||||
|
**Fiche** : `WIP/wechat_miniapp_homework.md`
|
||||||
|
**Description** : Mini Program WeChat pour devoirs audio/vidéo avec auto-correction AI
|
||||||
|
**Stack** : WeChat Mini Program (frontend), Node.js/Express (backend), Whisper, GPT-4
|
||||||
|
**Status** : CONCEPT → WIP (30 nov 2025)
|
||||||
|
**Horizon** : Plusieurs années (usage long terme enseignement)
|
||||||
|
**Timeline** : 15 jours dev complet estimé
|
||||||
|
|
||||||
|
### 5. SEO Article Generator
|
||||||
**Fiche** : `WIP/SEO_Article_Generator.md`
|
**Fiche** : `WIP/SEO_Article_Generator.md`
|
||||||
**Description** : Génération d'articles SEO avec anti-détection IA
|
**Description** : Génération d'articles SEO avec anti-détection IA
|
||||||
**Stack** : Node.js
|
**Stack** : Node.js
|
||||||
**Status** : En repurpose pour gérer du Fiverr
|
**Status** : En repurpose pour gérer du Fiverr
|
||||||
**Historique** : Voir archives pour status octobre 2025
|
**Historique** : Voir archives pour status octobre 2025
|
||||||
|
|
||||||
### 3. AISSIA
|
|
||||||
**Fiche** : `WIP/AISSIA.md`
|
|
||||||
**Description** : AI assistant basé sur GroveEngine
|
|
||||||
**Stack** : Basé sur GroveEngine
|
|
||||||
**Status** : Développement actif
|
|
||||||
|
|
||||||
### 4. SecondVoice
|
|
||||||
**Fiche** : `WIP/SecondVoice.md`
|
|
||||||
**Description** : Système de traduction en direct pour meetings chinois
|
|
||||||
**Stack** : À définir
|
|
||||||
**Status** : Développement actif
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -45,42 +57,54 @@
|
|||||||
|
|
||||||
### 1. Warfactory
|
### 1. Warfactory
|
||||||
**Fiche** : `PAUSE/Warfactory.md`
|
**Fiche** : `PAUSE/Warfactory.md`
|
||||||
**Description** : Jeu (engine en développement)
|
**Description** : Simulation militaire industrielle (Factorio + stratégie)
|
||||||
**Stack** : C++
|
**Stack** : C++
|
||||||
**Raison pause** : Focus sur GroveEngine
|
**Status** : Avance INDIRECTEMENT via GroveEngine
|
||||||
|
**Note** : Pas abandonné - GroveEngine = infrastructure pour Warfactory
|
||||||
**Historique** : Voir archives pour worldgen design oct 2025
|
**Historique** : Voir archives pour worldgen design oct 2025
|
||||||
|
|
||||||
### 2. chinese_audio_tts_pipeline
|
### 2. chinese_audio_tts_pipeline
|
||||||
**Fiche** : `PAUSE/chinese_audio_tts_pipeline.md`
|
**Fiche** : `PAUSE/chinese_audio_tts_pipeline.md`
|
||||||
**Description** : Pipeline TTS pour génération audio chinois
|
**Description** : Pipeline TTS pour génération audio chinois
|
||||||
**Stack** : Python
|
**Stack** : Python
|
||||||
**Status** : Utilisé pour Database chinois mais développement en pause
|
**Status** : OBSOLÈTE - Remplacé par videotoMP3Transcriptor
|
||||||
|
**Action suggérée** : ARCHIVE (doublon fonctionnel)
|
||||||
|
|
||||||
### 3. MCP_Game_Asset_Pipeline
|
### 3. MCP_Game_Asset_Pipeline
|
||||||
**Fiche** : `PAUSE/MCP_Game_Asset_Pipeline.md`
|
**Fiche** : `PAUSE/MCP_Game_Asset_Pipeline.md`
|
||||||
**Description** : Pipeline créatif AI pour génération assets de jeu
|
**Description** : Pipeline créatif AI pour génération assets de jeu (DALL-E, Suno, etc.)
|
||||||
**Stack** : MCP + AI
|
**Stack** : MCP + AI
|
||||||
**Target** : Warfactory
|
**Target** : Warfactory
|
||||||
**Status** : Concept/Vision pas encore implémenté
|
**Status** : Concept/Vision - Dépend de Warfactory (trop tôt)
|
||||||
|
|
||||||
### 4. ocr_pdf_service
|
### 4. Essay_Writing_Tingting
|
||||||
**Fiche** : `PAUSE/ocr_pdf_service.md`
|
|
||||||
**Description** : Service OCR en ligne pour PDFs (extraction texte + PDF searchable)
|
|
||||||
**Stack** : Node.js + PaddleOCR Python
|
|
||||||
**Créé** : 19 nov 2025
|
|
||||||
**Status** : Conception
|
|
||||||
|
|
||||||
### 5. Essay_Writing_Tingting
|
|
||||||
**Fiche** : `PAUSE/Essay_Writing_Tingting.md`
|
**Fiche** : `PAUSE/Essay_Writing_Tingting.md`
|
||||||
**Description** : Accompagnement Tingting pour écriture essais
|
**Description** : Accompagnement Tingting pour écriture essais
|
||||||
**Status** : Promesse faite, détails à clarifier
|
**Status** : Promesse faite, détails à clarifier
|
||||||
|
**Action requise** : Demander à Tingting cette semaine ou KILL
|
||||||
**Note** : Card créée dans daily check system (ACTION-008)
|
**Note** : Card créée dans daily check system (ACTION-008)
|
||||||
|
|
||||||
|
### 5. shipping_strategy
|
||||||
|
**Fiche** : `PAUSE/shipping_strategy/` (dossier)
|
||||||
|
**Description** : Meta-projet organisation shipping (dual-track père/perso)
|
||||||
|
**Status** : Documentation organisationnelle
|
||||||
|
**Action suggérée** : ARCHIVE (tu shippes déjà sans ce système - 102 commits/3 semaines)
|
||||||
|
|
||||||
|
### 6. SecondVoice
|
||||||
|
**Fiche** : `PAUSE/SecondVoice.md` (moved from WIP 30 nov 2025)
|
||||||
|
**Description** : Système traduction temps réel pour meetings chinois
|
||||||
|
**Stack** : À définir
|
||||||
|
**Status** : Tentative initiale échouée, relance prévue
|
||||||
|
**Note** : Besoin réel identifié (support Tingting + confort personnel meetings)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ♾️ CONSTANT (Projets perpétuels) - 3 projets
|
## ♾️ CONSTANT (Projets perpétuels) - 4 projets
|
||||||
|
|
||||||
### 1. civjdr - Civilisation de la Confluence
|
### 1. videotoMP3Transcriptor → MOVED TO DONE ✅
|
||||||
|
**Voir** : `DONE/videotoMP3Transcriptor.md`
|
||||||
|
|
||||||
|
### 2. civjdr - Civilisation de la Confluence
|
||||||
**Fiche** : `CONSTANT/civjdr.md`
|
**Fiche** : `CONSTANT/civjdr.md`
|
||||||
**Description** : JDR 4X construction de civilisation sur Discord
|
**Description** : JDR 4X construction de civilisation sur Discord
|
||||||
**Players** : GM (Arthur Ignatus) + Joueur (Rubanc/Alexis)
|
**Players** : GM (Arthur Ignatus) + Joueur (Rubanc/Alexis)
|
||||||
@ -88,15 +112,15 @@
|
|||||||
**Workflow** : Tours GM → Analyse → Réponse → Cycle
|
**Workflow** : Tours GM → Analyse → Réponse → Cycle
|
||||||
**Status** : Actif, cycles continus
|
**Status** : Actif, cycles continus
|
||||||
|
|
||||||
### 2. Database Cours Chinois
|
### 3. Database Cours Chinois
|
||||||
**Fiche** : `CONSTANT/Database_Cours_Chinois.md`
|
**Fiche** : `CONSTANT/Database_Cours_Chinois.md`
|
||||||
**Description** : Base de données apprentissage chinois
|
**Description** : Base de données apprentissage chinois
|
||||||
**Objectif** : Atteindre niveau Zhongyi (intermédiaire)
|
**Objectif** : Atteindre niveau Zhongyi (intermédiaire)
|
||||||
**Niveau actuel** : En dessous de Zhongyi
|
**Niveau actuel** : En dessous de Zhongyi
|
||||||
**Outils** : PDF, exercices, gestion IA
|
**Outils** : PDF, exercices, gestion IA, videotoMP3Transcriptor
|
||||||
**Historique** : Pipeline OCR validé oct 2025 (99.97% précision avec PaddleOCR)
|
**Historique** : Pipeline OCR validé oct 2025 (99.97% précision avec PaddleOCR)
|
||||||
|
|
||||||
### 3. Class Generator 2.0
|
### 4. Class Generator 2.0
|
||||||
**Fiche** : `CONSTANT/ClassGen_Analysis.md` + `Class_Generator_2.0.md`
|
**Fiche** : `CONSTANT/ClassGen_Analysis.md` + `Class_Generator_2.0.md`
|
||||||
**Description** : Plateforme éducative interactive (anglais/chinois, enfants 8-9 ans)
|
**Description** : Plateforme éducative interactive (anglais/chinois, enfants 8-9 ans)
|
||||||
**Stack** : Vanilla JS, Node.js
|
**Stack** : Vanilla JS, Node.js
|
||||||
@ -108,78 +132,144 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 💡 CONCEPT - 5 projets
|
## 💡 CONCEPT - 8 projets
|
||||||
|
|
||||||
### 1. pokrovsk_last_day
|
### 1. AI_Team_System
|
||||||
|
**Fiche** : `CONCEPT/AI_Team_System.md` (created 30 nov 2025)
|
||||||
|
**Description** : Système d'organisation IA complète (débat, décision, exécution autonome)
|
||||||
|
**Stack** : Multi-agents (Claude API), Vector DB, GitHub Actions
|
||||||
|
**Objectif** : Passer de 1 projet DONE/mois à 4-8 projets DONE/mois
|
||||||
|
**Status** : Concept complet - Validation Phase 0 requise
|
||||||
|
**ROI attendu** : 300-700% productivity gain sur fast shipping
|
||||||
|
**Infrastructure** : Potentiellement basé sur AISSIA
|
||||||
|
**Timeline estimée** : 1-1.5 mois (Hybrid approach)
|
||||||
|
|
||||||
|
### 2. ocr_pdf_service
|
||||||
|
**Fiche** : `CONCEPT/ocr_pdf_service.md` (moved from PAUSE 30 nov 2025)
|
||||||
|
**Description** : Service OCR en ligne pour PDFs (extraction texte + PDF searchable)
|
||||||
|
**Stack** : Node.js + PaddleOCR Python backend
|
||||||
|
**Modes** : Extraction texte brut OU PDF searchable avec texte intégré
|
||||||
|
**Status** : Conception - Pas de besoin immédiat identifié
|
||||||
|
|
||||||
|
### 2. pokrovsk_last_day
|
||||||
**Fiche** : `CONCEPT/pokrovsk_last_day.md`
|
**Fiche** : `CONCEPT/pokrovsk_last_day.md`
|
||||||
**Description** : Survival horror réaliste (guerre moderne Ukraine)
|
**Description** : Survival horror réaliste (guerre moderne Ukraine)
|
||||||
**Genre** : FPS/Survival horror, drones comme ennemi principal
|
**Genre** : FPS/Survival horror, drones comme ennemi principal
|
||||||
**Status** : Concept complet (41KB de design doc)
|
**Status** : Concept complet (41KB de design doc)
|
||||||
**Note** : Version gestion à discuter
|
**Note** : Version gestion à discuter
|
||||||
|
|
||||||
### 2. social_network_manager
|
### 3. social_network_manager
|
||||||
**Fiche** : `CONCEPT/social_network_manager.md`
|
**Fiche** : `CONCEPT/social_network_manager.md`
|
||||||
**Description** : Gestionnaire IA multi-plateformes sociales (6 plateformes)
|
**Description** : Gestionnaire IA multi-plateformes sociales (6 plateformes)
|
||||||
**Stack** : Browser-Use (Playwright + LLM vision)
|
**Stack** : Browser-Use (Playwright + LLM vision)
|
||||||
**Status** : Conception suspendue - Problèmes ToS/légaux
|
**Status** : Conception suspendue - Problèmes ToS/légaux
|
||||||
**Créé** : 27 oct 2025
|
**Créé** : 27 oct 2025
|
||||||
|
|
||||||
### 3. vps_tunnel_china
|
### 4. vps_tunnel_china
|
||||||
**Fiche** : `CONCEPT/vps_tunnel_china.md`
|
**Fiche** : `CONCEPT/vps_tunnel_china.md`
|
||||||
**Description** : Setup VPN anti-GFW (contourner Great Firewall)
|
**Description** : Setup VPN anti-GFW (contourner Great Firewall)
|
||||||
**Stack** : V2Ray/WireGuard + obfuscation + Cloudflare
|
**Stack** : V2Ray/WireGuard + obfuscation + Cloudflare
|
||||||
**Contexte** : Shanghai
|
**Contexte** : Shanghai
|
||||||
**Status** : Doc complète (400 lignes, roadmap, scripts) mais pas déployé
|
**Status** : Doc complète (400 lignes, roadmap, scripts) mais pas déployé
|
||||||
|
|
||||||
### 4. Claude_Workflow_Optimization
|
### 5. Claude_Workflow_Optimization
|
||||||
**Fiche** : `CONCEPT/Claude_Workflow_Optimization.md`
|
**Fiche** : `CONCEPT/Claude_Workflow_Optimization.md`
|
||||||
**Description** : Optimiser workflow multi-instances Claude
|
**Description** : Optimiser workflow multi-instances Claude
|
||||||
**Idées** : Hooks, slash commands, coordination multi-instances
|
**Idées** : Hooks, slash commands, coordination multi-instances
|
||||||
**Status** : Idée initiale, besoins à préciser
|
**Status** : Idée initiale, besoins à préciser
|
||||||
|
|
||||||
### 5. LeBonCoup (dossier)
|
### 7. Reddit_Save_Scraper
|
||||||
|
**Fiche** : `CONCEPT/Reddit_Save_Scraper.md` (created 30 nov 2025)
|
||||||
|
**Description** : Scraper posts Reddit sauvegardés + extraction valeur (knowledge base, digest, search)
|
||||||
|
**Stack** : Python + PRAW (Reddit API) ou Node.js + snoowrap
|
||||||
|
**Use cases** : Archive/backup, AI digest weekly, search UI, Anki cards generator
|
||||||
|
**Status** : Concept - Exploration requise (combien de saved posts ?)
|
||||||
|
**MVP timeline** : 1-2 jours
|
||||||
|
**Potentiel** : Test case parfait pour AI_Team_System
|
||||||
|
|
||||||
|
### 8. LeBonCoup (dossier)
|
||||||
**Status** : À examiner
|
**Status** : À examiner
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## ✅ DONE (Projets shipped et terminés) - 1 projet
|
||||||
|
|
||||||
|
### 1. videotoMP3Transcriptor
|
||||||
|
**Fiche** : `DONE/videotoMP3Transcriptor.md`
|
||||||
|
**Description** : Service YouTube → MP3 → Transcription → Traduction → Résumé
|
||||||
|
**Stack** : Node.js, Express, OpenAI (Whisper, GPT-4o-mini, GPT-5.1), yt-dlp, ffmpeg
|
||||||
|
**Shipped** : 25 novembre 2025 (2 jours de dev)
|
||||||
|
**Status** : En production, utilisé régulièrement pour cours chinois
|
||||||
|
**Note** : PREMIER PROJET DONE 🎉
|
||||||
|
**Code réutilisable** : 50% overlap avec homework bot (Whisper, Express, file processing)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 📦 ARCHIVE
|
## 📦 ARCHIVE
|
||||||
|
|
||||||
### Docs archivées
|
### Docs archivées
|
||||||
- `MCP_Creative_Amplification.md` - Guide MCP (14 oct 2025, 927 lignes)
|
- `MCP_Creative_Amplification.md` - Guide MCP (14 oct 2025, 927 lignes)
|
||||||
- `Backlog_9-10_Octobre_2025.md` - Log incident git + reconstruction
|
- `Backlog_9-10_Octobre_2025.md` - Log incident git + reconstruction
|
||||||
|
|
||||||
|
### Projets candidats ARCHIVE (action suggérée)
|
||||||
|
- `chinese_audio_tts_pipeline` - Obsolète (remplacé par videotoMP3)
|
||||||
|
- `shipping_strategy` - Meta-projet (tu shippes déjà sans)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📊 Statistiques
|
## 📊 Statistiques
|
||||||
|
|
||||||
**Total projets actifs** : 12 (4 WIP + 5 PAUSE + 3 CONSTANT)
|
**Total projets actifs** : 16 (5 WIP + 6 PAUSE + 4 CONSTANT)
|
||||||
**Projets concepts** : 5
|
**Projets concepts** : 8 (dont AI_Team_System - meta-projet, Reddit_Save_Scraper)
|
||||||
**Archivés** : 2 docs
|
**Projets DONE** : 1 (videotoMP3Transcriptor) 🎉
|
||||||
|
**Archivés** : 2 docs + 2 candidats
|
||||||
|
|
||||||
**Par domaine** :
|
**Par domaine** :
|
||||||
- Couple/Tingting : 1 (Essay Writing)
|
- Couple/Tingting : 1 (Essay Writing)
|
||||||
- Apprentissage : 2 (Database Chinois, Class Generator)
|
- Apprentissage : 2 (Database Chinois, Class Generator)
|
||||||
- Tech/IA : 4 (GroveEngine, AISSIA, SecondVoice, SEO)
|
- Tech/IA : 5 (GroveEngine, AISSIA, Confluent, SecondVoice, SEO)
|
||||||
- Gaming : 3 (Warfactory, MCP Assets, Pokrovsk)
|
- Gaming : 3 (Warfactory, MCP Assets, Pokrovsk)
|
||||||
- Créatif : 1 (civjdr)
|
- Créatif : 1 (civjdr)
|
||||||
- Services : 2 (OCR PDF, VPS Tunnel)
|
- Services : 3 (videotoMP3 DONE, OCR PDF, VPS Tunnel)
|
||||||
- Workflow : 2 (Social Network, Claude Workflow)
|
- Workflow : 2 (Social Network, Claude Workflow)
|
||||||
|
- Education : 1 (WeChat Homework Bot)
|
||||||
|
- Productivity : 1 (Reddit Save Scraper)
|
||||||
|
- Meta : 1 (AI_Team_System - multiplicateur de force)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🎯 Patterns Observés (Historique Oct 2025)
|
## 🎯 Patterns Observés
|
||||||
|
|
||||||
### Zone de Confort : C++ (Warfactory)
|
### Pattern Exécution (Validé Nov 2025)
|
||||||
|
|
||||||
|
**Données objectives (24 nov - 30 nov 2025)** :
|
||||||
|
- **102 commits** en 3 semaines (aissia: 33, groveengine: 46, confluent: 23)
|
||||||
|
- **71% temps actif** (15 jours actifs / 21 jours)
|
||||||
|
- **Premier projet DONE** (videotoMP3 - 2 jours conception → shipped)
|
||||||
|
|
||||||
|
**Verdict** : **TU EXÉCUTES.** Pas "plan only", pas "paralysie perfectionnisme".
|
||||||
|
|
||||||
|
**Pattern identifié** :
|
||||||
|
- ✅ Exécution massive quand projet activé
|
||||||
|
- ✅ Ship features complètes (tests, debug, validation)
|
||||||
|
- ✅ Progression logique (phases, milestones)
|
||||||
|
- ✅ Balance : Gros projets architecturaux (GroveEngine) + Fast shipping (videotoMP3)
|
||||||
|
|
||||||
|
**Le seul "problème"** : Multi-threading 3 gros projets simultanés → Dilution focus → Aucun "fini" rapidement MAIS tous 3 progressent vraiment.
|
||||||
|
|
||||||
|
### Zone de Confort : C++ (Warfactory, GroveEngine, AISSIA)
|
||||||
- ✅ Design rapide et efficace
|
- ✅ Design rapide et efficace
|
||||||
- ✅ Pas de perfectionnisme paralysant
|
- ✅ Pas de perfectionnisme paralysant
|
||||||
- ✅ Confiance dans les choix
|
- ✅ Confiance dans les choix
|
||||||
- **Raison** : Se sent légitime → Pas de menace identitaire
|
- **Raison** : Se sent légitime → Pas de menace identitaire
|
||||||
|
- **Preuve** : 46 commits GroveEngine + 33 commits AISSIA en 3 semaines
|
||||||
|
|
||||||
### Hors Zone : Node.js (SEO, ClassGen)
|
### Hors Zone : Node.js (SEO, ClassGen)
|
||||||
- ❌ Syndrome de l'imposteur
|
- ❌ Syndrome de l'imposteur (diminué avec expérience)
|
||||||
- ❌ Over-engineering compensatoire
|
- ❌ Over-engineering compensatoire
|
||||||
- ❌ Refactor en boucle
|
- ❌ Refactor en boucle
|
||||||
- **Raison** : Se sent imposteur → Sur-compensation
|
- **Raison** : Se sent imposteur → Sur-compensation
|
||||||
|
- **Contre-exemple** : videotoMP3 shipped en 2 jours (Node.js) → Pattern s'améliore
|
||||||
|
|
||||||
### Solution qui Marche
|
### Solution qui Marche
|
||||||
**Claude Code** : Compense difficulté d'exécution, garde partie conception (fun), délègue implémentation (chiante)
|
**Claude Code** : Compense difficulté d'exécution, garde partie conception (fun), délègue implémentation (chiante)
|
||||||
|
|||||||
@ -1,561 +0,0 @@
|
|||||||
# GroveEngine - RenderModule (Framework Module)
|
|
||||||
|
|
||||||
**Type** : Framework Module (base avancée)
|
|
||||||
**Stack** : bgfx + SDL2
|
|
||||||
**Objectif** : Window + UI 2D element rendering
|
|
||||||
**Dernière mise à jour** : 26 novembre 2025
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Vue d'ensemble
|
|
||||||
|
|
||||||
Module framework pour GroveEngine fournissant les capacités de rendu 2D de base :
|
|
||||||
- **Window management** via SDL2
|
|
||||||
- **Rendering 2D** via bgfx (multi-backend : Vulkan/DX12/Metal/OpenGL)
|
|
||||||
- **UI element rendering** (primitives 2D)
|
|
||||||
|
|
||||||
**Base avancée** = Intégration complète dans le GroveEngine + capacités rendering fonctionnelles
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Architecture Module
|
|
||||||
|
|
||||||
### Integration GroveEngine
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
class RenderModule : public grove::IModule {
|
|
||||||
public:
|
|
||||||
// IModule interface
|
|
||||||
void initialize(const IDataNode& config, IIO* io) override;
|
|
||||||
void update(float dt) override;
|
|
||||||
void shutdown() override;
|
|
||||||
|
|
||||||
// Rendering API
|
|
||||||
void BeginFrame();
|
|
||||||
void EndFrame();
|
|
||||||
|
|
||||||
// 2D Primitives
|
|
||||||
void DrawRect(const Rect& rect, Color color);
|
|
||||||
void DrawSprite(const Sprite& sprite);
|
|
||||||
void DrawText(const std::string& text, Font font, Vec2 pos);
|
|
||||||
|
|
||||||
private:
|
|
||||||
SDL_Window* window;
|
|
||||||
bgfx::ViewId main_view;
|
|
||||||
Renderer2D renderer;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### Composants Clés
|
|
||||||
|
|
||||||
**1. Window Management (SDL2)**
|
|
||||||
```cpp
|
|
||||||
struct WindowConfig {
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
std::string title;
|
|
||||||
bool fullscreen;
|
|
||||||
bool vsync;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Création window SDL2
|
|
||||||
window = SDL_CreateWindow(
|
|
||||||
config.title.c_str(),
|
|
||||||
SDL_WINDOWPOS_CENTERED,
|
|
||||||
SDL_WINDOWPOS_CENTERED,
|
|
||||||
config.width,
|
|
||||||
config.height,
|
|
||||||
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
**2. bgfx Initialization**
|
|
||||||
```cpp
|
|
||||||
bgfx::Init init;
|
|
||||||
init.type = bgfx::RendererType::Count; // Auto-detect
|
|
||||||
init.resolution.width = width;
|
|
||||||
init.resolution.height = height;
|
|
||||||
init.resolution.reset = BGFX_RESET_VSYNC;
|
|
||||||
|
|
||||||
// Utilise window SDL2
|
|
||||||
SDL_SysWMinfo wmi;
|
|
||||||
SDL_VERSION(&wmi.version);
|
|
||||||
SDL_GetWindowWMInfo(window, &wmi);
|
|
||||||
|
|
||||||
#if BX_PLATFORM_WINDOWS
|
|
||||||
init.platformData.nwh = wmi.info.win.window;
|
|
||||||
#elif BX_PLATFORM_LINUX
|
|
||||||
init.platformData.ndt = wmi.info.x11.display;
|
|
||||||
init.platformData.nwh = (void*)(uintptr_t)wmi.info.x11.window;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bgfx::init(init);
|
|
||||||
```
|
|
||||||
|
|
||||||
**3. Renderer2D (Primitives)**
|
|
||||||
```cpp
|
|
||||||
class Renderer2D {
|
|
||||||
public:
|
|
||||||
void DrawRect(const Rect& rect, Color color);
|
|
||||||
void DrawSprite(const Sprite& sprite);
|
|
||||||
void Flush(); // Submit batched draws
|
|
||||||
|
|
||||||
private:
|
|
||||||
bgfx::ProgramHandle sprite_shader;
|
|
||||||
bgfx::ProgramHandle color_shader;
|
|
||||||
|
|
||||||
struct SpriteBatch {
|
|
||||||
std::vector<SpriteVertex> vertices;
|
|
||||||
bgfx::TextureHandle texture;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<SpriteBatch> batches;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Rendering Pipeline
|
|
||||||
|
|
||||||
### Frame Structure
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
void RenderModule::update(float dt) {
|
|
||||||
BeginFrame();
|
|
||||||
|
|
||||||
// Rendering commands
|
|
||||||
DrawRect({100, 100, 200, 150}, Color::Red());
|
|
||||||
DrawSprite(test_sprite);
|
|
||||||
DrawText("Hello GroveEngine", main_font, {50, 50});
|
|
||||||
|
|
||||||
EndFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderModule::BeginFrame() {
|
|
||||||
bgfx::touch(main_view);
|
|
||||||
bgfx::setViewClear(main_view,
|
|
||||||
BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH,
|
|
||||||
0x303030ff, 1.0f, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderModule::EndFrame() {
|
|
||||||
renderer.Flush(); // Submit batched draws
|
|
||||||
bgfx::frame(); // Advance frame
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Vertex Formats
|
|
||||||
|
|
||||||
**Sprite Vertex (textured quad)**
|
|
||||||
```cpp
|
|
||||||
struct SpriteVertex {
|
|
||||||
float x, y, z; // Position
|
|
||||||
float u, v; // UV coords
|
|
||||||
uint32_t color; // Tint (ABGR)
|
|
||||||
};
|
|
||||||
|
|
||||||
bgfx::VertexLayout sprite_layout;
|
|
||||||
sprite_layout.begin()
|
|
||||||
.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
|
|
||||||
.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
|
|
||||||
.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
|
|
||||||
.end();
|
|
||||||
```
|
|
||||||
|
|
||||||
**Color Vertex (solid color quad)**
|
|
||||||
```cpp
|
|
||||||
struct ColorVertex {
|
|
||||||
float x, y, z;
|
|
||||||
uint32_t color;
|
|
||||||
};
|
|
||||||
|
|
||||||
bgfx::VertexLayout color_layout;
|
|
||||||
color_layout.begin()
|
|
||||||
.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
|
|
||||||
.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
|
|
||||||
.end();
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Shaders
|
|
||||||
|
|
||||||
### Sprite Shader (Vertex)
|
|
||||||
|
|
||||||
```glsl
|
|
||||||
// vs_sprite.sc
|
|
||||||
$input a_position, a_texcoord0, a_color0
|
|
||||||
$output v_texcoord0, v_color0
|
|
||||||
|
|
||||||
#include <bgfx_shader.sh>
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0));
|
|
||||||
v_texcoord0 = a_texcoord0;
|
|
||||||
v_color0 = a_color0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Sprite Shader (Fragment)
|
|
||||||
|
|
||||||
```glsl
|
|
||||||
// fs_sprite.sc
|
|
||||||
$input v_texcoord0, v_color0
|
|
||||||
|
|
||||||
#include <bgfx_shader.sh>
|
|
||||||
|
|
||||||
SAMPLER2D(s_texture, 0);
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec4 texColor = texture2D(s_texture, v_texcoord0);
|
|
||||||
gl_FragColor = texColor * v_color0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Compilation** :
|
|
||||||
```bash
|
|
||||||
shaderc -f vs_sprite.sc -o vs_sprite.bin --type vertex --platform linux -p 120
|
|
||||||
shaderc -f fs_sprite.sc -o fs_sprite.bin --type fragment --platform linux -p 120
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Camera 2D
|
|
||||||
|
|
||||||
### Orthographic Projection
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
class Camera2D {
|
|
||||||
public:
|
|
||||||
Vec2 position;
|
|
||||||
float zoom = 1.0f;
|
|
||||||
|
|
||||||
Mat4 GetViewMatrix() const {
|
|
||||||
return Mat4::Translation(-position.x, -position.y, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 GetProjectionMatrix(int width, int height) const {
|
|
||||||
float halfW = (width / zoom) * 0.5f;
|
|
||||||
float halfH = (height / zoom) * 0.5f;
|
|
||||||
return Mat4::Ortho(-halfW, halfW, -halfH, halfH, -1, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Setup view transform
|
|
||||||
Mat4 view = camera.GetViewMatrix();
|
|
||||||
Mat4 proj = camera.GetProjectionMatrix(screenW, screenH);
|
|
||||||
bgfx::setViewTransform(main_view, view.data, proj.data);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## UI Element Rendering
|
|
||||||
|
|
||||||
### DrawRect Implementation
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
void Renderer2D::DrawRect(const Rect& rect, Color color) {
|
|
||||||
ColorVertex vertices[4] = {
|
|
||||||
{rect.x, rect.y, 0, color.abgr()},
|
|
||||||
{rect.x + rect.w, rect.y, 0, color.abgr()},
|
|
||||||
{rect.x + rect.w, rect.y + rect.h, 0, color.abgr()},
|
|
||||||
{rect.x, rect.y + rect.h, 0, color.abgr()}
|
|
||||||
};
|
|
||||||
|
|
||||||
uint16_t indices[6] = {0, 1, 2, 0, 2, 3};
|
|
||||||
|
|
||||||
bgfx::TransientVertexBuffer tvb;
|
|
||||||
bgfx::TransientIndexBuffer tib;
|
|
||||||
|
|
||||||
bgfx::allocTransientVertexBuffer(&tvb, 4, color_layout);
|
|
||||||
bgfx::allocTransientIndexBuffer(&tib, 6);
|
|
||||||
|
|
||||||
memcpy(tvb.data, vertices, sizeof(vertices));
|
|
||||||
memcpy(tib.data, indices, sizeof(indices));
|
|
||||||
|
|
||||||
bgfx::setVertexBuffer(0, &tvb);
|
|
||||||
bgfx::setIndexBuffer(&tib);
|
|
||||||
bgfx::setState(BGFX_STATE_DEFAULT);
|
|
||||||
bgfx::submit(main_view, color_shader);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### DrawSprite Implementation (Batched)
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
void Renderer2D::DrawSprite(const Sprite& sprite) {
|
|
||||||
// Find or create batch for this texture
|
|
||||||
SpriteBatch* batch = GetBatchForTexture(sprite.texture);
|
|
||||||
|
|
||||||
// Add quad to batch
|
|
||||||
float x0 = sprite.pos.x;
|
|
||||||
float y0 = sprite.pos.y;
|
|
||||||
float x1 = x0 + sprite.size.x;
|
|
||||||
float y1 = y0 + sprite.size.y;
|
|
||||||
|
|
||||||
uint32_t color = sprite.tint.abgr();
|
|
||||||
|
|
||||||
batch->vertices.push_back({x0, y0, 0, 0, 0, color});
|
|
||||||
batch->vertices.push_back({x1, y0, 0, 1, 0, color});
|
|
||||||
batch->vertices.push_back({x1, y1, 0, 1, 1, color});
|
|
||||||
batch->vertices.push_back({x0, y1, 0, 0, 1, color});
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer2D::Flush() {
|
|
||||||
for (auto& batch : batches) {
|
|
||||||
size_t quad_count = batch.vertices.size() / 4;
|
|
||||||
|
|
||||||
// Generate indices (0,1,2, 0,2,3 per quad)
|
|
||||||
std::vector<uint16_t> indices;
|
|
||||||
for (size_t i = 0; i < quad_count; ++i) {
|
|
||||||
uint16_t base = i * 4;
|
|
||||||
indices.push_back(base + 0);
|
|
||||||
indices.push_back(base + 1);
|
|
||||||
indices.push_back(base + 2);
|
|
||||||
indices.push_back(base + 0);
|
|
||||||
indices.push_back(base + 2);
|
|
||||||
indices.push_back(base + 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Submit draw call
|
|
||||||
bgfx::TransientVertexBuffer tvb;
|
|
||||||
bgfx::TransientIndexBuffer tib;
|
|
||||||
|
|
||||||
bgfx::allocTransientVertexBuffer(&tvb, batch.vertices.size(), sprite_layout);
|
|
||||||
bgfx::allocTransientIndexBuffer(&tib, indices.size());
|
|
||||||
|
|
||||||
memcpy(tvb.data, batch.vertices.data(), batch.vertices.size() * sizeof(SpriteVertex));
|
|
||||||
memcpy(tib.data, indices.data(), indices.size() * sizeof(uint16_t));
|
|
||||||
|
|
||||||
bgfx::setTexture(0, sampler, batch.texture);
|
|
||||||
bgfx::setVertexBuffer(0, &tvb);
|
|
||||||
bgfx::setIndexBuffer(&tib);
|
|
||||||
bgfx::setState(BGFX_STATE_DEFAULT);
|
|
||||||
bgfx::submit(main_view, sprite_shader);
|
|
||||||
}
|
|
||||||
|
|
||||||
batches.clear();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Configuration Module
|
|
||||||
|
|
||||||
### Config File (JSON)
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"module": "RenderModule",
|
|
||||||
"window": {
|
|
||||||
"width": 1280,
|
|
||||||
"height": 720,
|
|
||||||
"title": "GroveEngine - RenderModule Test",
|
|
||||||
"fullscreen": false,
|
|
||||||
"vsync": true
|
|
||||||
},
|
|
||||||
"rendering": {
|
|
||||||
"clear_color": "#303030",
|
|
||||||
"main_view_id": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Loading Config
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
void RenderModule::initialize(const IDataNode& config, IIO* io) {
|
|
||||||
WindowConfig window_config;
|
|
||||||
window_config.width = config.get("window.width", 1280);
|
|
||||||
window_config.height = config.get("window.height", 720);
|
|
||||||
window_config.title = config.get("window.title", "GroveEngine");
|
|
||||||
window_config.vsync = config.get("window.vsync", true);
|
|
||||||
|
|
||||||
InitializeWindow(window_config);
|
|
||||||
InitializeBgfx(window_config);
|
|
||||||
InitializeRenderer();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Roadmap Développement
|
|
||||||
|
|
||||||
### Phase 1 - Window + Init (Semaine 1)
|
|
||||||
|
|
||||||
**Objectif** : Window SDL2 + bgfx initialized, clear screen
|
|
||||||
|
|
||||||
- [ ] Setup SDL2 window
|
|
||||||
- [ ] Initialize bgfx avec window handle
|
|
||||||
- [ ] Clear screen avec couleur
|
|
||||||
- [ ] Main loop fonctionnel
|
|
||||||
- [ ] Event handling basique (close window)
|
|
||||||
|
|
||||||
**Livrable** : Window qui affiche fond gris, ferme proprement
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Phase 2 - Primitives 2D (Semaine 2)
|
|
||||||
|
|
||||||
**Objectif** : DrawRect fonctionnel
|
|
||||||
|
|
||||||
- [ ] Vertex layouts (ColorVertex, SpriteVertex)
|
|
||||||
- [ ] Shader compilation (color shader)
|
|
||||||
- [ ] DrawRect implementation
|
|
||||||
- [ ] Camera 2D orthographic
|
|
||||||
- [ ] Afficher 1 rectangle coloré
|
|
||||||
|
|
||||||
**Livrable** : Fenêtre avec rectangle rouge affiché
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Phase 3 - Sprite Rendering (Semaine 3)
|
|
||||||
|
|
||||||
**Objectif** : DrawSprite fonctionnel
|
|
||||||
|
|
||||||
- [ ] Texture loading (stb_image)
|
|
||||||
- [ ] Sprite shader (vertex + fragment)
|
|
||||||
- [ ] DrawSprite implementation (batched)
|
|
||||||
- [ ] Afficher 1 sprite texturé
|
|
||||||
|
|
||||||
**Livrable** : Fenêtre avec sprite test affiché
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Phase 4 - UI Elements (Semaine 4)
|
|
||||||
|
|
||||||
**Objectif** : Text rendering + UI primitives
|
|
||||||
|
|
||||||
- [ ] Font loading (stb_truetype ou FreeType)
|
|
||||||
- [ ] DrawText implementation
|
|
||||||
- [ ] UI element base class
|
|
||||||
- [ ] UIPanel, UIText primitives
|
|
||||||
|
|
||||||
**Livrable** : Fenêtre avec panneau UI + texte
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Dépendances
|
|
||||||
|
|
||||||
### Externes (Libraries)
|
|
||||||
|
|
||||||
- **SDL2** : Window + input
|
|
||||||
- **bgfx** : Rendering abstraction
|
|
||||||
- **bx** : Base library (bgfx dependency)
|
|
||||||
- **bimg** : Image loading (bgfx dependency)
|
|
||||||
- **stb_image** : Texture loading
|
|
||||||
- **stb_truetype** ou **FreeType** : Font rendering
|
|
||||||
|
|
||||||
### GroveEngine (Internes)
|
|
||||||
|
|
||||||
- `IModule` interface
|
|
||||||
- `IDataNode` (config system)
|
|
||||||
- `IIO` (inter-module communication)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Test Case - Base Avancée
|
|
||||||
|
|
||||||
### Validation Criteria
|
|
||||||
|
|
||||||
**Window + UI 2D element = base avancée validée** si :
|
|
||||||
|
|
||||||
1. ✅ Window SDL2 créée et stable
|
|
||||||
2. ✅ bgfx initialisé et rendering fonctionnel
|
|
||||||
3. ✅ DrawRect affiche rectangle coloré
|
|
||||||
4. ✅ DrawSprite affiche sprite texturé
|
|
||||||
5. ✅ DrawText affiche texte (police)
|
|
||||||
6. ✅ UI element (panel) rendu correctement
|
|
||||||
7. ✅ Module intégré dans GroveEngine (IModule interface)
|
|
||||||
|
|
||||||
### Example Test Code
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
// main.cpp
|
|
||||||
int main() {
|
|
||||||
auto engine = grove::EngineFactory::CreateDebugEngine();
|
|
||||||
|
|
||||||
auto config = LoadConfig("render_module_config.json");
|
|
||||||
engine->LoadModule("RenderModule", config);
|
|
||||||
|
|
||||||
// Game loop
|
|
||||||
while (!should_quit) {
|
|
||||||
engine->Update(dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dans RenderModule::update()
|
|
||||||
void RenderModule::update(float dt) {
|
|
||||||
BeginFrame();
|
|
||||||
|
|
||||||
// Test: Rectangle
|
|
||||||
DrawRect({100, 100, 200, 100}, Color{255, 0, 0, 255});
|
|
||||||
|
|
||||||
// Test: Sprite
|
|
||||||
DrawSprite(test_sprite);
|
|
||||||
|
|
||||||
// Test: UI Panel
|
|
||||||
DrawRect({50, 50, 300, 200}, Color{64, 64, 64, 200});
|
|
||||||
DrawText("Base Avancée OK!", main_font, {60, 60});
|
|
||||||
|
|
||||||
EndFrame();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Questions Ouvertes
|
|
||||||
|
|
||||||
### Architecture
|
|
||||||
|
|
||||||
1. **Text rendering** : stb_truetype (simple) ou FreeType (complet) ?
|
|
||||||
2. **Asset management** : AssetManager séparé ou intégré dans RenderModule ?
|
|
||||||
3. **Multi-window** : Support futur ou single window only ?
|
|
||||||
|
|
||||||
### Performance
|
|
||||||
|
|
||||||
4. **Sprite batching** : Sort by texture ou sort by Z-order ?
|
|
||||||
5. **Transient buffers** : OK pour MVP ou besoin persistent buffers ?
|
|
||||||
|
|
||||||
### Integration
|
|
||||||
|
|
||||||
6. **ImGui** : Garder ImGuiUI.h existant ou remplacer par custom UI ?
|
|
||||||
7. **Hot-reload** : Shader hot-reload nécessaire ou compilation statique OK ?
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Ressources
|
|
||||||
|
|
||||||
### Documentation bgfx
|
|
||||||
|
|
||||||
- Repo : https://github.com/bkaradzic/bgfx
|
|
||||||
- Examples : https://github.com/bkaradzic/bgfx/tree/master/examples
|
|
||||||
- API docs : https://bkaradzic.github.io/bgfx/
|
|
||||||
|
|
||||||
### Tutorials 2D avec bgfx
|
|
||||||
|
|
||||||
- bgfx example-26 (vectordisplay)
|
|
||||||
- NanoVG-bgfx : https://github.com/memononen/nanovg
|
|
||||||
|
|
||||||
### SDL2
|
|
||||||
|
|
||||||
- Wiki : https://wiki.libsdl.org/
|
|
||||||
- Lazy Foo tutorials : https://lazyfoo.net/tutorials/SDL/
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Liens Projets
|
|
||||||
|
|
||||||
- **GroveEngine core** : `Projects/WIP/GroveEngine.md`
|
|
||||||
- **GroveEngine architecture** : `Projects/WIP/grove-sup.md`
|
|
||||||
- **Aissia** (utilisateur) : `Projects/WIP/AISSIA.md`
|
|
||||||
- **Pokrovsk** (utilisateur futur) : `Projects/CONCEPT/pokrovsk_last_day.md`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Créé** : 26 novembre 2025
|
|
||||||
**Status** : Architecture planning
|
|
||||||
**Type** : Framework module (base avancée)
|
|
||||||
**Objectif** : Window + UI 2D rendering pour GroveEngine
|
|
||||||
659
Projects/WIP/ProjectOrganizer.md
Normal file
@ -0,0 +1,659 @@
|
|||||||
|
# ProjectOrganizer - GroveEngine Module
|
||||||
|
|
||||||
|
## Vue d'ensemble
|
||||||
|
|
||||||
|
Module GroveEngine C++ pour analyse, classification et organisation automatique de dossiers de projets avec génération de visualisations et rapports.
|
||||||
|
|
||||||
|
### Objectif
|
||||||
|
|
||||||
|
Créer un module GroveEngine qui :
|
||||||
|
- Analyse récursivement un dossier projet
|
||||||
|
- Classifie et organise tous les documents
|
||||||
|
- Détecte et mappe les relations entre fichiers
|
||||||
|
- Génère des visualisations (graphes de dépendances)
|
||||||
|
- Produit des outputs structurés (JSON, Markdown, HTML)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Spécifications Techniques
|
||||||
|
|
||||||
|
### Intégration GroveEngine
|
||||||
|
|
||||||
|
**Type** : IModule (DLL/SO hot-reloadable)
|
||||||
|
|
||||||
|
**Communication** : Via IIO (IntraIO)
|
||||||
|
|
||||||
|
**Architecture** :
|
||||||
|
```
|
||||||
|
Application
|
||||||
|
↓
|
||||||
|
GroveEngine (IEngine)
|
||||||
|
↓
|
||||||
|
ProjectOrganizerModule (IModule)
|
||||||
|
├─ Reçoit requêtes via IIO
|
||||||
|
├─ Analyse filesystem
|
||||||
|
├─ Classifie/organise
|
||||||
|
├─ Génère outputs
|
||||||
|
└─ Retourne résultats via IIO
|
||||||
|
```
|
||||||
|
|
||||||
|
### API IIO
|
||||||
|
|
||||||
|
**Input messages** :
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "analyze",
|
||||||
|
"source_path": "/path/to/project",
|
||||||
|
"output_path": "/path/to/results",
|
||||||
|
"options": {
|
||||||
|
"use_llm": false,
|
||||||
|
"file_types": ["txt", "md", "pdf", "doc", "docx", "ppt", "pptx"],
|
||||||
|
"max_depth": -1,
|
||||||
|
"generate_graphs": true,
|
||||||
|
"copy_source": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output messages** :
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "success",
|
||||||
|
"output_path": "/path/to/results",
|
||||||
|
"stats": {
|
||||||
|
"files_processed": 142,
|
||||||
|
"files_classified": 138,
|
||||||
|
"relations_found": 67,
|
||||||
|
"duration_ms": 1243
|
||||||
|
},
|
||||||
|
"summary": {
|
||||||
|
"categories": {
|
||||||
|
"documentation": 45,
|
||||||
|
"code": 23,
|
||||||
|
"config": 12,
|
||||||
|
"data": 58
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fonctionnalités
|
||||||
|
|
||||||
|
### Phase 1 - MVP Sans LLM (Court terme)
|
||||||
|
|
||||||
|
**Formats supportés** : `.txt`, `.md`
|
||||||
|
|
||||||
|
**Capacités** :
|
||||||
|
- [x] Copie récursive du dossier source
|
||||||
|
- [x] Scan tous fichiers txt/md
|
||||||
|
- [x] Classification basique par :
|
||||||
|
- Extension de fichier
|
||||||
|
- Localisation (dossier parent)
|
||||||
|
- Patterns dans nom fichier
|
||||||
|
- [x] Détection relations :
|
||||||
|
- Liens markdown `[text](file.md)`
|
||||||
|
- Références explicites chemin fichier
|
||||||
|
- Mentions de noms de fichiers
|
||||||
|
- [x] Génération outputs :
|
||||||
|
- JSON : Structure complète + métadonnées
|
||||||
|
- Markdown : Rapport lisible + index
|
||||||
|
- HTML : Visualisation interactive
|
||||||
|
|
||||||
|
**Graphes générés** :
|
||||||
|
- Graph de dépendances (qui référence qui)
|
||||||
|
- Graph de catégories (regroupement thématique)
|
||||||
|
- Graph de structure (arborescence dossiers)
|
||||||
|
|
||||||
|
**Livrables** :
|
||||||
|
```
|
||||||
|
output/
|
||||||
|
├── organized/ # Copie organisée du projet
|
||||||
|
│ ├── documentation/
|
||||||
|
│ ├── code/
|
||||||
|
│ ├── config/
|
||||||
|
│ └── data/
|
||||||
|
├── analysis/
|
||||||
|
│ ├── structure.json # Données brutes
|
||||||
|
│ ├── relations.json # Graphe de relations
|
||||||
|
│ ├── report.md # Rapport markdown
|
||||||
|
│ └── index.html # Visualisation interactive
|
||||||
|
└── graphs/
|
||||||
|
├── dependencies.svg
|
||||||
|
├── categories.svg
|
||||||
|
└── structure.svg
|
||||||
|
```
|
||||||
|
|
||||||
|
**Durée estimée** : 1-2 semaines
|
||||||
|
|
||||||
|
### Phase 2 - Formats Avancés (Moyen terme)
|
||||||
|
|
||||||
|
**Nouveaux formats** : `.pdf` (OCR), `.doc`, `.docx`, `.ppt`, `.pptx`
|
||||||
|
|
||||||
|
**Capacités additionnelles** :
|
||||||
|
- [x] Extraction texte PDF avec OCR (Tesseract/PaddleOCR)
|
||||||
|
- [x] Parsing Office documents (LibreOffice SDK / Apache POI via JNI)
|
||||||
|
- [x] Détection langage automatique
|
||||||
|
- [x] Extraction métadonnées (auteur, date, tags)
|
||||||
|
|
||||||
|
**Durée estimée** : 2-3 semaines
|
||||||
|
|
||||||
|
### Phase 3 - Analyse LLM (Long terme)
|
||||||
|
|
||||||
|
**Intégration LLM** : Via IIO vers module LLM externe
|
||||||
|
|
||||||
|
**Capacités LLM** :
|
||||||
|
- Classification sémantique profonde
|
||||||
|
- Détection relations implicites
|
||||||
|
- Extraction concepts clés
|
||||||
|
- Génération résumés
|
||||||
|
- Suggestions réorganisation
|
||||||
|
|
||||||
|
**Architecture** :
|
||||||
|
```
|
||||||
|
ProjectOrganizerModule
|
||||||
|
↓ (IIO message)
|
||||||
|
LLMModule (Claude/GPT via API)
|
||||||
|
↓ (response)
|
||||||
|
ProjectOrganizerModule
|
||||||
|
```
|
||||||
|
|
||||||
|
**Durée estimée** : 3-4 semaines
|
||||||
|
|
||||||
|
### Phase 4 - Analyse Code (Très long terme)
|
||||||
|
|
||||||
|
**Langages supportés** : C++, Python, JavaScript, Java, etc.
|
||||||
|
|
||||||
|
**Capacités** :
|
||||||
|
- Parsing AST (Abstract Syntax Tree)
|
||||||
|
- Détection dépendances imports
|
||||||
|
- Call graph génération
|
||||||
|
- Détection fonctions inutilisées
|
||||||
|
- Analyse complexité
|
||||||
|
|
||||||
|
**Outils** :
|
||||||
|
- Clang LibTooling (C++)
|
||||||
|
- Tree-sitter (multi-langage)
|
||||||
|
- LSP integration possible
|
||||||
|
|
||||||
|
**Note** : Pas prioritaire, code n'est pas la target principale
|
||||||
|
|
||||||
|
**Durée estimée** : 4-6 semaines
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Workflows Typiques
|
||||||
|
|
||||||
|
### Workflow 1 : Analyse Projet Existant
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// 1. User lance via IIO
|
||||||
|
io->send("ProjectOrganizer", {
|
||||||
|
"action": "analyze",
|
||||||
|
"source_path": "E:/Projets/MyProject",
|
||||||
|
"output_path": "E:/Projets/MyProject_Analysis"
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Module process
|
||||||
|
// - Copie récursive
|
||||||
|
// - Scan fichiers
|
||||||
|
// - Classification
|
||||||
|
// - Détection relations
|
||||||
|
// - Génération outputs
|
||||||
|
|
||||||
|
// 3. Module répond
|
||||||
|
io->receive([](const Message& msg) {
|
||||||
|
if (msg.status == "success") {
|
||||||
|
// Ouvrir index.html
|
||||||
|
system("start E:/Projets/MyProject_Analysis/analysis/index.html");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Workflow 2 : Watch Mode (Future)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Mode surveillance continue
|
||||||
|
io->send("ProjectOrganizer", {
|
||||||
|
"action": "watch",
|
||||||
|
"source_path": "E:/Projets/MyProject",
|
||||||
|
"update_interval_ms": 5000
|
||||||
|
});
|
||||||
|
|
||||||
|
// Module update analysis automatiquement toutes les 5s
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture Interne Module
|
||||||
|
|
||||||
|
### Classes Principales
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Module principal
|
||||||
|
class ProjectOrganizerModule : public IModule {
|
||||||
|
public:
|
||||||
|
void initialize(const IDataNode& config, IIO* io) override;
|
||||||
|
void update(float deltaTime) override;
|
||||||
|
void shutdown() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
FileScanner scanner_;
|
||||||
|
Classifier classifier_;
|
||||||
|
RelationDetector relationDetector_;
|
||||||
|
OutputGenerator outputGenerator_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Scanner filesystem
|
||||||
|
class FileScanner {
|
||||||
|
public:
|
||||||
|
std::vector<FileInfo> scanRecursive(const std::string& path);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Classification fichiers
|
||||||
|
class Classifier {
|
||||||
|
public:
|
||||||
|
Category classify(const FileInfo& file);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Détection relations
|
||||||
|
class RelationDetector {
|
||||||
|
public:
|
||||||
|
std::vector<Relation> detect(const std::vector<FileInfo>& files);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Génération outputs
|
||||||
|
class OutputGenerator {
|
||||||
|
public:
|
||||||
|
void generateJSON(const Analysis& analysis, const std::string& path);
|
||||||
|
void generateMarkdown(const Analysis& analysis, const std::string& path);
|
||||||
|
void generateHTML(const Analysis& analysis, const std::string& path);
|
||||||
|
void generateGraphs(const Analysis& analysis, const std::string& path);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Structures de Données
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct FileInfo {
|
||||||
|
std::string path;
|
||||||
|
std::string name;
|
||||||
|
std::string extension;
|
||||||
|
size_t size;
|
||||||
|
time_t modified;
|
||||||
|
Category category;
|
||||||
|
std::string content; // Si text-based
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Category {
|
||||||
|
Documentation,
|
||||||
|
Code,
|
||||||
|
Config,
|
||||||
|
Data,
|
||||||
|
Media,
|
||||||
|
Archive,
|
||||||
|
Unknown
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Relation {
|
||||||
|
std::string from; // Fichier source
|
||||||
|
std::string to; // Fichier cible
|
||||||
|
RelationType type; // Link, Import, Reference
|
||||||
|
std::string context; // Ligne où trouvé
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Analysis {
|
||||||
|
std::vector<FileInfo> files;
|
||||||
|
std::vector<Relation> relations;
|
||||||
|
std::map<Category, int> stats;
|
||||||
|
std::chrono::milliseconds duration;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dépendances
|
||||||
|
|
||||||
|
### Requises (Phase 1)
|
||||||
|
|
||||||
|
- **C++17** : Filesystem API (`<filesystem>`)
|
||||||
|
- **nlohmann_json** : Génération JSON (déjà dans GroveEngine)
|
||||||
|
- **Graphviz** : Génération graphes SVG (external process call)
|
||||||
|
|
||||||
|
### Optionnelles (Phases 2+)
|
||||||
|
|
||||||
|
- **Tesseract/PaddleOCR** : OCR pour PDFs
|
||||||
|
- **LibreOffice SDK** : Parsing Office documents
|
||||||
|
- **Tree-sitter** : Parsing code (Phase 4)
|
||||||
|
|
||||||
|
### Note
|
||||||
|
|
||||||
|
Toutes les dépendances lourdes (LLM, OCR) via IIO vers modules externes, pas intégrées directement.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Génération Visualisations
|
||||||
|
|
||||||
|
### Format Graphviz DOT
|
||||||
|
|
||||||
|
**Example dependencies graph** :
|
||||||
|
```dot
|
||||||
|
digraph dependencies {
|
||||||
|
rankdir=LR;
|
||||||
|
node [shape=box];
|
||||||
|
|
||||||
|
"README.md" -> "docs/architecture.md";
|
||||||
|
"README.md" -> "docs/setup.md";
|
||||||
|
"src/main.cpp" -> "include/engine.h";
|
||||||
|
"include/engine.h" -> "include/module.h";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Génération** :
|
||||||
|
```cpp
|
||||||
|
void OutputGenerator::generateGraphs(const Analysis& analysis, const std::string& path) {
|
||||||
|
// 1. Créer fichier DOT
|
||||||
|
std::ofstream dot(path + "/dependencies.dot");
|
||||||
|
dot << "digraph dependencies {\n";
|
||||||
|
for (const auto& rel : analysis.relations) {
|
||||||
|
dot << " \"" << rel.from << "\" -> \"" << rel.to << "\";\n";
|
||||||
|
}
|
||||||
|
dot << "}\n";
|
||||||
|
dot.close();
|
||||||
|
|
||||||
|
// 2. Appeler Graphviz
|
||||||
|
system("dot -Tsvg dependencies.dot -o dependencies.svg");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Format HTML Interactif
|
||||||
|
|
||||||
|
**Technologies** :
|
||||||
|
- **vis.js** : Graphes interactifs
|
||||||
|
- **D3.js** : Alternative visualisations
|
||||||
|
- **Bootstrap** : UI propre
|
||||||
|
|
||||||
|
**Features** :
|
||||||
|
- Zoom/pan sur graphe
|
||||||
|
- Click fichier → Affiche infos
|
||||||
|
- Filtres par catégorie
|
||||||
|
- Search bar
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
### Cibles
|
||||||
|
|
||||||
|
- **Scan 1000 fichiers** : < 1s
|
||||||
|
- **Classification** : < 100ms (sans LLM)
|
||||||
|
- **Détection relations** : < 500ms
|
||||||
|
- **Génération outputs** : < 2s
|
||||||
|
|
||||||
|
### Optimisations
|
||||||
|
|
||||||
|
- Multi-threading scan filesystem
|
||||||
|
- Cache résultats (inotify/FileSystemWatcher pour détecter changements)
|
||||||
|
- Lazy loading contenu fichier (seulement si nécessaire)
|
||||||
|
- Streaming génération HTML (pas tout en RAM)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration Module
|
||||||
|
|
||||||
|
**Fichier config** : `config/project_organizer.json`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"default_output_path": "~/.groveengine/project_analysis",
|
||||||
|
"file_types": {
|
||||||
|
"phase1": ["txt", "md"],
|
||||||
|
"phase2": ["pdf", "doc", "docx", "ppt", "pptx"],
|
||||||
|
"phase4": ["cpp", "h", "py", "js", "java"]
|
||||||
|
},
|
||||||
|
"classification_rules": {
|
||||||
|
"documentation": ["README", "docs/", ".md"],
|
||||||
|
"code": ["src/", "include/", ".cpp", ".h"],
|
||||||
|
"config": ["config/", ".json", ".yaml", ".toml"]
|
||||||
|
},
|
||||||
|
"graph_engine": "graphviz",
|
||||||
|
"max_file_size_mb": 10,
|
||||||
|
"use_cache": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
### Tests Unitaires
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
TEST(FileScanner, ScanRecursive) {
|
||||||
|
FileScanner scanner;
|
||||||
|
auto files = scanner.scanRecursive("test_data/sample_project");
|
||||||
|
EXPECT_GT(files.size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Classifier, ClassifyMarkdown) {
|
||||||
|
Classifier classifier;
|
||||||
|
FileInfo file{"README.md", "README.md", "md", 1024, 0, Category::Unknown, ""};
|
||||||
|
EXPECT_EQ(classifier.classify(file), Category::Documentation);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(RelationDetector, DetectMarkdownLinks) {
|
||||||
|
RelationDetector detector;
|
||||||
|
FileInfo file{"test.md", "test.md", "md", 0, 0, Category::Unknown,
|
||||||
|
"See [other](other.md) for details"};
|
||||||
|
auto relations = detector.detect({file});
|
||||||
|
EXPECT_EQ(relations.size(), 1);
|
||||||
|
EXPECT_EQ(relations[0].to, "other.md");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tests Intégration
|
||||||
|
|
||||||
|
- Test projet réel (couple_matters repo)
|
||||||
|
- Validation outputs générés
|
||||||
|
- Performance benchmarks
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Roadmap Développement
|
||||||
|
|
||||||
|
### Phase 1 - MVP (1-2 semaines)
|
||||||
|
- [ ] Setup module GroveEngine boilerplate
|
||||||
|
- [ ] FileScanner implementation
|
||||||
|
- [ ] Classifier basique (extension + path)
|
||||||
|
- [ ] RelationDetector markdown links
|
||||||
|
- [ ] OutputGenerator JSON + MD
|
||||||
|
- [ ] Tests unitaires basiques
|
||||||
|
- [ ] Exemple fonctionnel
|
||||||
|
|
||||||
|
### Phase 2 - Formats Avancés (2-3 semaines)
|
||||||
|
- [ ] Intégration OCR (PDF)
|
||||||
|
- [ ] Parser Office docs
|
||||||
|
- [ ] OutputGenerator HTML interactif
|
||||||
|
- [ ] Graph generation (Graphviz)
|
||||||
|
- [ ] Performance optimizations
|
||||||
|
- [ ] Tests intégration
|
||||||
|
|
||||||
|
### Phase 3 - LLM (3-4 semaines)
|
||||||
|
- [ ] IIO protocol vers LLM module
|
||||||
|
- [ ] Classification sémantique
|
||||||
|
- [ ] Détection relations implicites
|
||||||
|
- [ ] Génération résumés
|
||||||
|
- [ ] A/B testing LLM vs non-LLM
|
||||||
|
|
||||||
|
### Phase 4 - Code Analysis (4-6 semaines)
|
||||||
|
- [ ] Tree-sitter integration
|
||||||
|
- [ ] AST parsing multi-langage
|
||||||
|
- [ ] Call graph generation
|
||||||
|
- [ ] Unused code detection
|
||||||
|
- [ ] Complexity metrics
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Problèmes Anticipés
|
||||||
|
|
||||||
|
### 1. Performance Gros Projets
|
||||||
|
|
||||||
|
**Problème** : Projet 10,000+ fichiers = scan lent
|
||||||
|
|
||||||
|
**Solutions** :
|
||||||
|
- Multi-threading (std::async)
|
||||||
|
- Filtrage intelligent (ignorer node_modules, .git)
|
||||||
|
- Incremental analysis (cache + watch mode)
|
||||||
|
|
||||||
|
### 2. Encodings Fichiers
|
||||||
|
|
||||||
|
**Problème** : Fichiers UTF-8, UTF-16, ISO-8859-1, etc.
|
||||||
|
|
||||||
|
**Solutions** :
|
||||||
|
- Auto-détection encoding (libiconv/ICU)
|
||||||
|
- Fallback UTF-8 + ignore errors
|
||||||
|
- Log fichiers non-parsables
|
||||||
|
|
||||||
|
### 3. Graphes Trop Complexes
|
||||||
|
|
||||||
|
**Problème** : 1000+ nodes = illisible
|
||||||
|
|
||||||
|
**Solutions** :
|
||||||
|
- Clustering par catégorie
|
||||||
|
- Zoom levels (overview → détail)
|
||||||
|
- Filtres interactifs HTML
|
||||||
|
|
||||||
|
### 4. Faux Positifs Relations
|
||||||
|
|
||||||
|
**Problème** : Détecte "test.md" dans commentaire comme lien
|
||||||
|
|
||||||
|
**Solutions** :
|
||||||
|
- Heuristiques strictes (markdown syntax only)
|
||||||
|
- LLM validation (Phase 3)
|
||||||
|
- Whitelist/blacklist user
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exemples Utilisation
|
||||||
|
|
||||||
|
### Exemple 1 : Analyse couple_matters Repo
|
||||||
|
|
||||||
|
**Input** :
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "analyze",
|
||||||
|
"source_path": "E:/Users/Alexis Trouvé/Documents/Projets/couple_matters",
|
||||||
|
"output_path": "E:/couple_matters_analysis"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output attendu** :
|
||||||
|
- 200+ fichiers markdown classifiés
|
||||||
|
- Relations détectées :
|
||||||
|
- `CLAUDE.md` → `ToRemember/schema.md`
|
||||||
|
- `personnalités/Tingting.md` → `personnalités/TingtingWork.md`
|
||||||
|
- `Projects/Status_Projets.md` → tous les `Projects/*/projet.md`
|
||||||
|
- Graphe catégories :
|
||||||
|
- Couple (50%)
|
||||||
|
- Projets (30%)
|
||||||
|
- Planning (10%)
|
||||||
|
- Autres (10%)
|
||||||
|
|
||||||
|
### Exemple 2 : Analyse Codebase C++
|
||||||
|
|
||||||
|
**Input** :
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "analyze",
|
||||||
|
"source_path": "E:/Projets/GroveEngine",
|
||||||
|
"options": {
|
||||||
|
"file_types": ["cpp", "h", "md"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output attendu** :
|
||||||
|
- Headers classifiés par module
|
||||||
|
- Includes graph
|
||||||
|
- Documentation liée au code
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Risques
|
||||||
|
|
||||||
|
| Risque | Probabilité | Impact | Mitigation |
|
||||||
|
|--------|-------------|--------|------------|
|
||||||
|
| **Over-engineering** | Élevée | Moyen | MVP strict Phase 1, features après |
|
||||||
|
| **Performance inacceptable gros projets** | Moyenne | Élevé | Benchmarks early, optimizations prioritaires |
|
||||||
|
| **OCR/Office parsing complexe** | Moyenne | Moyen | Phase 2 optionnelle, focus txt/md d'abord |
|
||||||
|
| **Graphviz dépendance externe** | Faible | Faible | Fallback text-based graph si absent |
|
||||||
|
| **Scope creep vers IDE** | Élevée | Élevé | Focus analyse/organisation, pas édition |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Statut Actuel
|
||||||
|
|
||||||
|
### Code
|
||||||
|
- ❌ Aucun code écrit
|
||||||
|
- ❌ Module pas créé dans GroveEngine
|
||||||
|
|
||||||
|
### Design
|
||||||
|
- ✅ Spécifications complètes
|
||||||
|
- ✅ API IIO définie
|
||||||
|
- ✅ Architecture interne définie
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
- ❌ Aucun test
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
- ✅ Ce fichier (fiche projet)
|
||||||
|
- ⏳ Guide utilisateur à écrire
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prochaines Étapes
|
||||||
|
|
||||||
|
### Immédiat
|
||||||
|
1. [ ] Créer `GroveEngine/modules/ProjectOrganizer/` folder structure
|
||||||
|
2. [ ] Setup CMake pour module
|
||||||
|
3. [ ] Créer squelette `ProjectOrganizerModule.cpp`
|
||||||
|
4. [ ] Implement FileScanner basique
|
||||||
|
5. [ ] Test scan sur petit projet
|
||||||
|
|
||||||
|
### Court terme
|
||||||
|
1. [ ] Classifier implementation
|
||||||
|
2. [ ] RelationDetector markdown
|
||||||
|
3. [ ] OutputGenerator JSON
|
||||||
|
4. [ ] Test sur couple_matters repo
|
||||||
|
|
||||||
|
### Moyen terme
|
||||||
|
1. [ ] OutputGenerator Markdown + HTML
|
||||||
|
2. [ ] Graphviz integration
|
||||||
|
3. [ ] Performance optimization
|
||||||
|
4. [ ] Documentation utilisateur
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ressources
|
||||||
|
|
||||||
|
### Repos
|
||||||
|
- **GroveEngine** : `E:/Projets/GroveEngine/`
|
||||||
|
- **Module location** : `E:/Projets/GroveEngine/modules/ProjectOrganizer/`
|
||||||
|
- **Test data** : `E:/Users/Alexis Trouvé/Documents/Projets/couple_matters/`
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
- `GroveEngine/docs/architecture-modulaire.md` : Système IModule
|
||||||
|
- `GroveEngine/docs/CLAUDE-HOT-RELOAD-GUIDE.md` : Hot-reload workflow
|
||||||
|
|
||||||
|
### External Tools
|
||||||
|
- **Graphviz** : https://graphviz.org/
|
||||||
|
- **vis.js** : https://visjs.org/
|
||||||
|
- **PaddleOCR** : https://github.com/PaddlePaddle/PaddleOCR (Phase 2)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Créé : 28 novembre 2025*
|
||||||
|
*Statut : CONCEPT → WIP (Phase 1)*
|
||||||
|
*Stack : C++17, GroveEngine IModule, nlohmann_json, Graphviz*
|
||||||
|
*Target : Analyse/organisation projets documentation-heavy*
|
||||||
@ -1,746 +0,0 @@
|
|||||||
# GroveEngine - Supplementary Design Document
|
|
||||||
|
|
||||||
**Date créé** : 24 novembre 2025
|
|
||||||
**Auteur** : Alexis (avec Claude Code)
|
|
||||||
**Status** : Architecture Planning
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## CONTEXTE
|
|
||||||
|
|
||||||
**GroveEngine** est un moteur de jeu multi-projets conçu pour être :
|
|
||||||
- **Data-driven** : Config/text-based pour tout ce qui est modifiable
|
|
||||||
- **AI-friendly** : LLM peut créer/modifier assets sans toucher au code C++
|
|
||||||
- **Multi-backend rendering** : Support Vulkan/DX12/Metal/OpenGL via bgfx
|
|
||||||
- **Solide & réutilisable** : Foundation pour plusieurs projets
|
|
||||||
|
|
||||||
**État actuel** :
|
|
||||||
- ✅ Coeur engine done (mode debug)
|
|
||||||
- ❌ Pas de rendering
|
|
||||||
- ❌ Pas de framework 2D/UI
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## PROJETS BASÉS SUR GROVEENGINE
|
|
||||||
|
|
||||||
1. **Pokrovsk: Iron Line** (survival management, train builder)
|
|
||||||
2. **AISSIA** (concepts via SecondVoice/YT-DL)
|
|
||||||
3. **Troisième projet** : À définir
|
|
||||||
|
|
||||||
**Objectif** : Un seul moteur, plusieurs jeux, maintenance centralisée.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## STACK TECHNIQUE
|
|
||||||
|
|
||||||
### Rendering
|
|
||||||
- **bgfx** : Abstraction multi-backend (Vulkan/DX12/Metal/OpenGL)
|
|
||||||
- Multi-platform par design
|
|
||||||
- Performant pour 2D (batching, sprites)
|
|
||||||
- Mature (utilisé par Defold engine)
|
|
||||||
- Dev : Branimir Karadzic (ex-Frostbite EA)
|
|
||||||
|
|
||||||
- **SDL2** : Windowing + input
|
|
||||||
- Cross-platform
|
|
||||||
- Léger, bien supporté
|
|
||||||
|
|
||||||
- **stb_image** : Texture loading
|
|
||||||
- Single-header, simple
|
|
||||||
|
|
||||||
### Serialization/Config
|
|
||||||
- **yaml-cpp** : YAML parsing
|
|
||||||
- Entities definitions
|
|
||||||
- Missions, events, dialogues
|
|
||||||
|
|
||||||
- **nlohmann/json** : JSON parsing
|
|
||||||
- UI layouts
|
|
||||||
- Save files
|
|
||||||
- Asset manifests (alternative)
|
|
||||||
|
|
||||||
- **TOML++** : Config files
|
|
||||||
- Settings, constants
|
|
||||||
- Game balance values
|
|
||||||
|
|
||||||
### UI
|
|
||||||
- **ImGui** : Debug/tools UI (dev only)
|
|
||||||
- Immediate mode
|
|
||||||
- Parfait pour tools
|
|
||||||
|
|
||||||
- **Custom UI system** (bgfx-based) : In-game UI
|
|
||||||
- JSON-driven layouts
|
|
||||||
- Rendering via bgfx
|
|
||||||
- Themeable
|
|
||||||
|
|
||||||
### Scripting (optionnel)
|
|
||||||
- **Lua** : Si besoin de scripting pour game logic
|
|
||||||
- **Alternative** : Config-only (YAML events + state machines)
|
|
||||||
- Plus simple
|
|
||||||
- Assez pour beaucoup de cas
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ARCHITECTURE AI-FRIENDLY
|
|
||||||
|
|
||||||
**Principe** : LLM peut créer/modifier game content sans toucher au code C++.
|
|
||||||
|
|
||||||
### 1. Entity System (Data-Driven)
|
|
||||||
|
|
||||||
**Structure** :
|
|
||||||
```
|
|
||||||
entities/
|
|
||||||
├── wagons/
|
|
||||||
│ ├── wagon_basic.yaml
|
|
||||||
│ ├── wagon_armored.yaml
|
|
||||||
│ └── wagon_workshop.yaml
|
|
||||||
├── drones/
|
|
||||||
│ ├── mavic_reco.yaml
|
|
||||||
│ └── fpv_strike.yaml
|
|
||||||
└── humans/
|
|
||||||
└── commandant_template.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
**Exemple : entities/wagons/wagon_basic.yaml**
|
|
||||||
```yaml
|
|
||||||
entity: wagon_basic
|
|
||||||
components:
|
|
||||||
- type: visual
|
|
||||||
sprite: wagon_base.png
|
|
||||||
size: [20, 6] # Grille interne
|
|
||||||
|
|
||||||
- type: balance
|
|
||||||
weight: 5.0
|
|
||||||
center_of_mass: [10, 3]
|
|
||||||
dampeners: 0 # Upgrade level
|
|
||||||
|
|
||||||
- type: slots
|
|
||||||
grid: [20, 6]
|
|
||||||
layers: [high, low]
|
|
||||||
specialization: null # production, logistic, habitation, military
|
|
||||||
|
|
||||||
- type: health
|
|
||||||
hp_max: 100
|
|
||||||
armor: 10
|
|
||||||
```
|
|
||||||
|
|
||||||
**LLM peut** : Créer nouveaux wagons, tweaker stats, ajouter composants.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. UI Layouts (Declarative JSON)
|
|
||||||
|
|
||||||
**Structure** :
|
|
||||||
```
|
|
||||||
ui/
|
|
||||||
├── screens/
|
|
||||||
│ ├── train_builder.json
|
|
||||||
│ ├── mission_briefing.json
|
|
||||||
│ └── campaign_map.json
|
|
||||||
└── widgets/
|
|
||||||
├── balance_gauge.json
|
|
||||||
└── resource_panel.json
|
|
||||||
```
|
|
||||||
|
|
||||||
**Exemple : ui/screens/train_builder.json**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"screen": "train_builder",
|
|
||||||
"elements": [
|
|
||||||
{
|
|
||||||
"type": "panel",
|
|
||||||
"id": "wagon_view",
|
|
||||||
"rect": [0, 0, 800, 600],
|
|
||||||
"background": "#2a2a2a",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"type": "sprite",
|
|
||||||
"id": "wagon_display",
|
|
||||||
"anchor": "center"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "gauge",
|
|
||||||
"id": "balance_lateral",
|
|
||||||
"rect": [820, 20, 160, 40],
|
|
||||||
"label": "Balance G/D",
|
|
||||||
"min": -10,
|
|
||||||
"max": 10,
|
|
||||||
"value_binding": "wagon.balance.lateral",
|
|
||||||
"color_good": "#00ff00",
|
|
||||||
"color_warning": "#ffaa00",
|
|
||||||
"color_bad": "#ff0000"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"id": "wagon_name",
|
|
||||||
"rect": [820, 80, 160, 30],
|
|
||||||
"text_binding": "wagon.name",
|
|
||||||
"font": "main_ui",
|
|
||||||
"size": 18,
|
|
||||||
"color": "#ffffff"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**LLM peut** : Créer UI screens, repositionner éléments, modifier styles, créer layouts.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. Game Logic (Config-Driven Events)
|
|
||||||
|
|
||||||
**Structure** :
|
|
||||||
```
|
|
||||||
content/
|
|
||||||
├── missions/
|
|
||||||
│ ├── 2022_early/
|
|
||||||
│ │ ├── scavenge_kyiv.yaml
|
|
||||||
│ │ └── rescue_civilians.yaml
|
|
||||||
│ └── 2025_late/
|
|
||||||
│ └── drone_intercept.yaml
|
|
||||||
├── events/
|
|
||||||
│ ├── random_events.yaml
|
|
||||||
│ └── story_events.yaml
|
|
||||||
└── dialogues/
|
|
||||||
└── commandants/
|
|
||||||
├── sergei.yaml
|
|
||||||
└── oksana.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
**Exemple : missions/2022_early/scavenge_kyiv.yaml**
|
|
||||||
```yaml
|
|
||||||
mission:
|
|
||||||
id: scavenge_kyiv_outskirts
|
|
||||||
name: "Colonne russe détruite - Périphérie Kyiv"
|
|
||||||
year: 2022
|
|
||||||
period: early
|
|
||||||
difficulty: easy
|
|
||||||
|
|
||||||
briefing:
|
|
||||||
text: |
|
|
||||||
Colonne blindée russe détruite à 2km au nord.
|
|
||||||
Reconnaissance indique 8-10 véhicules abandonnés.
|
|
||||||
Opposition minimale attendue.
|
|
||||||
|
|
||||||
intel:
|
|
||||||
- "Matériel récent, peu endommagé"
|
|
||||||
- "Zone relativement sécurisée"
|
|
||||||
- "Temps limité avant arrivée autres scavengers"
|
|
||||||
|
|
||||||
rewards:
|
|
||||||
metal: [50, 100]
|
|
||||||
electronics: [20, 40]
|
|
||||||
components_military: [5, 15]
|
|
||||||
fame: 10
|
|
||||||
|
|
||||||
risks:
|
|
||||||
- type: ambush
|
|
||||||
probability: 0.1
|
|
||||||
- type: mines
|
|
||||||
probability: 0.15
|
|
||||||
|
|
||||||
events:
|
|
||||||
- trigger: mission_start
|
|
||||||
text: "Votre équipe approche la colonne détruite..."
|
|
||||||
choices:
|
|
||||||
- id: approach_cautious
|
|
||||||
text: "Approche prudente (sweep mines)"
|
|
||||||
time_cost: 2h
|
|
||||||
risk_modifier: -0.5
|
|
||||||
|
|
||||||
- id: rush
|
|
||||||
text: "Rush rapide (grab & go)"
|
|
||||||
time_cost: 30min
|
|
||||||
risk_modifier: +0.8
|
|
||||||
reward_modifier: 1.2
|
|
||||||
|
|
||||||
- trigger: loot_phase
|
|
||||||
condition: "approach_cautious"
|
|
||||||
text: "Temps de fouiller méthodiquement..."
|
|
||||||
outcomes:
|
|
||||||
- probability: 0.7
|
|
||||||
result: success
|
|
||||||
rewards_modifier: 1.0
|
|
||||||
- probability: 0.3
|
|
||||||
result: partial
|
|
||||||
rewards_modifier: 0.6
|
|
||||||
```
|
|
||||||
|
|
||||||
**LLM peut** : Créer missions, events, dialogues, choix, outcomes.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 4. Asset Pipeline (Text Metadata)
|
|
||||||
|
|
||||||
**Structure** :
|
|
||||||
```
|
|
||||||
assets/
|
|
||||||
├── sprites/
|
|
||||||
│ ├── wagons.manifest
|
|
||||||
│ ├── drones.manifest
|
|
||||||
│ └── ui.manifest
|
|
||||||
├── textures/
|
|
||||||
│ └── (PNG files)
|
|
||||||
└── fonts/
|
|
||||||
└── fonts.manifest
|
|
||||||
```
|
|
||||||
|
|
||||||
**Exemple : assets/sprites/wagons.manifest (TOML)**
|
|
||||||
```toml
|
|
||||||
[wagon_base]
|
|
||||||
file = "textures/wagon_base.png"
|
|
||||||
size = [400, 120]
|
|
||||||
pivot = [200, 60]
|
|
||||||
tags = ["wagon", "basic"]
|
|
||||||
|
|
||||||
[wagon_armored]
|
|
||||||
file = "textures/wagon_armored.png"
|
|
||||||
size = [400, 120]
|
|
||||||
pivot = [200, 60]
|
|
||||||
weight_modifier = 1.5
|
|
||||||
tags = ["wagon", "armored", "heavy"]
|
|
||||||
|
|
||||||
[wagon_workshop]
|
|
||||||
file = "textures/wagon_workshop.png"
|
|
||||||
size = [400, 140] # Plus haut
|
|
||||||
pivot = [200, 70]
|
|
||||||
specialization = "production"
|
|
||||||
tags = ["wagon", "specialized"]
|
|
||||||
```
|
|
||||||
|
|
||||||
**LLM peut** : Définir assets, metadata, tags, modifiers.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ARCHITECTURE ENGINE
|
|
||||||
|
|
||||||
### Core Systems
|
|
||||||
|
|
||||||
**1. Entity Component System (ECS)**
|
|
||||||
```cpp
|
|
||||||
class Entity {
|
|
||||||
EntityID id;
|
|
||||||
std::vector<Component*> components;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Component {
|
|
||||||
virtual void Update(float dt) = 0;
|
|
||||||
virtual void Serialize(YAML::Node& node) = 0;
|
|
||||||
virtual void Deserialize(const YAML::Node& node) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Exemples components
|
|
||||||
class VisualComponent : public Component { ... }
|
|
||||||
class BalanceComponent : public Component { ... }
|
|
||||||
class SlotsComponent : public Component { ... }
|
|
||||||
```
|
|
||||||
|
|
||||||
**2. Asset Manager**
|
|
||||||
```cpp
|
|
||||||
class AssetManager {
|
|
||||||
// Textures
|
|
||||||
std::map<std::string, bgfx::TextureHandle> textures;
|
|
||||||
|
|
||||||
// Manifests (metadata)
|
|
||||||
std::map<std::string, AssetMetadata> metadata;
|
|
||||||
|
|
||||||
// Fonts
|
|
||||||
std::map<std::string, FontHandle> fonts;
|
|
||||||
|
|
||||||
void LoadManifest(const std::string& path);
|
|
||||||
bgfx::TextureHandle GetTexture(const std::string& id);
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
**3. Config System**
|
|
||||||
```cpp
|
|
||||||
class ConfigManager {
|
|
||||||
YAML::Node LoadYAML(const std::string& path);
|
|
||||||
nlohmann::json LoadJSON(const std::string& path);
|
|
||||||
|
|
||||||
Entity* CreateEntityFromYAML(const std::string& entity_id);
|
|
||||||
UIScreen* CreateUIFromJSON(const std::string& screen_id);
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
**4. Rendering 2D (bgfx-based)**
|
|
||||||
```cpp
|
|
||||||
class Renderer2D {
|
|
||||||
bgfx::ProgramHandle sprite_shader;
|
|
||||||
|
|
||||||
// Sprite batching pour performance
|
|
||||||
struct SpriteBatch {
|
|
||||||
std::vector<SpriteVertex> vertices;
|
|
||||||
bgfx::TextureHandle texture;
|
|
||||||
};
|
|
||||||
|
|
||||||
void DrawSprite(const Sprite& sprite);
|
|
||||||
void DrawRect(const Rect& rect, Color color);
|
|
||||||
void DrawText(const std::string& text, Font font, Vec2 pos);
|
|
||||||
|
|
||||||
void Flush(); // Submit batched draws
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
**5. UI System (JSON-driven)**
|
|
||||||
```cpp
|
|
||||||
class UIManager {
|
|
||||||
std::map<std::string, UIScreen*> screens;
|
|
||||||
|
|
||||||
UIScreen* LoadScreen(const std::string& screen_json);
|
|
||||||
void Update(float dt);
|
|
||||||
void Render(Renderer2D& renderer);
|
|
||||||
|
|
||||||
// Data binding
|
|
||||||
void BindValue(const std::string& path, float* value);
|
|
||||||
void BindText(const std::string& path, std::string* text);
|
|
||||||
};
|
|
||||||
|
|
||||||
class UIElement {
|
|
||||||
std::string id;
|
|
||||||
Rect rect;
|
|
||||||
virtual void Render(Renderer2D& renderer) = 0;
|
|
||||||
virtual void Update(float dt) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Concrete elements
|
|
||||||
class UIPanel : public UIElement { ... }
|
|
||||||
class UIGauge : public UIElement { ... }
|
|
||||||
class UIText : public UIElement { ... }
|
|
||||||
class UISprite : public UIElement { ... }
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## RENDERING 2D AVEC BGFX
|
|
||||||
|
|
||||||
### Concept de base
|
|
||||||
|
|
||||||
**bgfx ne fait PAS de 2D directement** → Tu construis la couche 2D par-dessus.
|
|
||||||
|
|
||||||
### Primitive : Quad (pour sprites)
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
struct SpriteVertex {
|
|
||||||
float x, y, z; // Position
|
|
||||||
float u, v; // UV coords (texture)
|
|
||||||
uint32_t color; // Tint color (ABGR)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Vertex layout bgfx
|
|
||||||
bgfx::VertexLayout sprite_layout;
|
|
||||||
sprite_layout.begin()
|
|
||||||
.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
|
|
||||||
.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
|
|
||||||
.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
|
|
||||||
.end();
|
|
||||||
```
|
|
||||||
|
|
||||||
### Sprite Rendering
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
void Renderer2D::DrawSprite(const Sprite& sprite) {
|
|
||||||
// 1. Batch sprite (grouper par texture)
|
|
||||||
GetOrCreateBatch(sprite.texture).AddQuad(sprite);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer2D::Flush() {
|
|
||||||
// 2. Pour chaque batch, submit draw call
|
|
||||||
for (auto& batch : batches) {
|
|
||||||
bgfx::setTexture(0, sampler, batch.texture);
|
|
||||||
bgfx::setVertexBuffer(0, batch.vertex_buffer);
|
|
||||||
bgfx::setIndexBuffer(batch.index_buffer);
|
|
||||||
bgfx::setState(BGFX_STATE_DEFAULT);
|
|
||||||
bgfx::submit(view_id, sprite_shader);
|
|
||||||
}
|
|
||||||
batches.clear();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Camera 2D (Orthographic)
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
class Camera2D {
|
|
||||||
Vec2 position;
|
|
||||||
float zoom;
|
|
||||||
|
|
||||||
Mat4 GetViewMatrix() const {
|
|
||||||
return Mat4::Translation(-position.x, -position.y, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 GetProjectionMatrix(int width, int height) const {
|
|
||||||
float halfW = (width / zoom) * 0.5f;
|
|
||||||
float halfH = (height / zoom) * 0.5f;
|
|
||||||
return Mat4::Ortho(-halfW, halfW, -halfH, halfH, -1, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Usage
|
|
||||||
bgfx::setViewTransform(view_id,
|
|
||||||
camera.GetViewMatrix().data,
|
|
||||||
camera.GetProjectionMatrix(screenW, screenH).data
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## PLAN DE DÉVELOPPEMENT
|
|
||||||
|
|
||||||
### Phase 1 : Core Engine (3-4 semaines)
|
|
||||||
|
|
||||||
**Semaine 1-2 : Setup bgfx + SDL2**
|
|
||||||
- [ ] Intégrer bgfx, bx, bimg dans projet (git submodules)
|
|
||||||
- [ ] Build bgfx pour platform cible
|
|
||||||
- [ ] Window SDL2 + init bgfx
|
|
||||||
- [ ] Clear screen avec couleur
|
|
||||||
- [ ] Input basique (keyboard, mouse)
|
|
||||||
|
|
||||||
**Semaine 3 : Rendering 2D basique**
|
|
||||||
- [ ] Vertex layout sprites
|
|
||||||
- [ ] Shader simple (texture + color tint)
|
|
||||||
- [ ] Afficher 1 sprite (quad texturé)
|
|
||||||
- [ ] Camera 2D orthographique
|
|
||||||
|
|
||||||
**Semaine 4 : Asset Pipeline**
|
|
||||||
- [ ] Texture loading (stb_image)
|
|
||||||
- [ ] AssetManager basique
|
|
||||||
- [ ] Manifest TOML (assets metadata)
|
|
||||||
- [ ] Load sprite from manifest
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Phase 2 : Framework 2D (2-3 semaines)
|
|
||||||
|
|
||||||
**Semaine 5 : Sprite System**
|
|
||||||
- [ ] Sprite batching (group by texture)
|
|
||||||
- [ ] DrawSprite API
|
|
||||||
- [ ] DrawRect (colored quads)
|
|
||||||
- [ ] Transform system (position, rotation, scale)
|
|
||||||
|
|
||||||
**Semaine 6 : UI Primitives**
|
|
||||||
- [ ] Text rendering (stb_truetype ou FreeType)
|
|
||||||
- [ ] Font loading via manifest
|
|
||||||
- [ ] DrawText API
|
|
||||||
- [ ] UI elements basiques (Panel, Text, Sprite)
|
|
||||||
|
|
||||||
**Semaine 7 : Input & Interaction**
|
|
||||||
- [ ] Mouse picking (screen → world coords)
|
|
||||||
- [ ] Drag & drop basique
|
|
||||||
- [ ] Button clicks
|
|
||||||
- [ ] Input manager
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Phase 3 : Entity System (2-3 semaines)
|
|
||||||
|
|
||||||
**Semaine 8 : ECS Core**
|
|
||||||
- [ ] Entity class
|
|
||||||
- [ ] Component base class
|
|
||||||
- [ ] Entity manager (create, destroy, query)
|
|
||||||
- [ ] YAML serialization/deserialization
|
|
||||||
|
|
||||||
**Semaine 9 : Components Library**
|
|
||||||
- [ ] VisualComponent (sprite rendering)
|
|
||||||
- [ ] TransformComponent (position, rotation)
|
|
||||||
- [ ] BalanceComponent (pour Pokrovsk wagons)
|
|
||||||
- [ ] SlotsComponent (grille placement)
|
|
||||||
|
|
||||||
**Semaine 10 : Config Integration**
|
|
||||||
- [ ] Load entity from YAML
|
|
||||||
- [ ] Entity templates system
|
|
||||||
- [ ] Component factory (deserialize components)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Phase 4 : UI System (2-3 semaines)
|
|
||||||
|
|
||||||
**Semaine 11 : UI Framework**
|
|
||||||
- [ ] UIElement base class
|
|
||||||
- [ ] UIManager (screen stack)
|
|
||||||
- [ ] Layout system (anchors, rects)
|
|
||||||
- [ ] JSON UI loading
|
|
||||||
|
|
||||||
**Semaine 12 : UI Widgets**
|
|
||||||
- [ ] UIPanel
|
|
||||||
- [ ] UIText (with data binding)
|
|
||||||
- [ ] UIGauge (progress bar, balance gauge)
|
|
||||||
- [ ] UIButton
|
|
||||||
|
|
||||||
**Semaine 13 : Advanced UI**
|
|
||||||
- [ ] Data binding system (link UI ↔ game data)
|
|
||||||
- [ ] Events (onClick, onHover)
|
|
||||||
- [ ] Theming (colors, fonts from config)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Phase 5 : Validation Pokrovsk (2-3 semaines)
|
|
||||||
|
|
||||||
**Semaine 14 : Wagon Entity**
|
|
||||||
- [ ] Wagon YAML definition
|
|
||||||
- [ ] Instantiate wagon from config
|
|
||||||
- [ ] Render wagon sprite (double slice)
|
|
||||||
- [ ] Display balance gauges (UI)
|
|
||||||
|
|
||||||
**Semaine 15 : Train Builder UI**
|
|
||||||
- [ ] Train builder screen (JSON)
|
|
||||||
- [ ] Grid overlay (slots)
|
|
||||||
- [ ] Drag & drop elements (atelier, stockage, dortoir)
|
|
||||||
- [ ] Real-time balance calculation
|
|
||||||
|
|
||||||
**Semaine 16 : Polish & Validation**
|
|
||||||
- [ ] Balance visualization (wagon tilts if unbalanced)
|
|
||||||
- [ ] Element placement constraints
|
|
||||||
- [ ] Save/load train configuration
|
|
||||||
- [ ] Prototype jouable = validation complète
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**TOTAL : ~10-16 semaines pour moteur complet + prototype Pokrovsk**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## AVANTAGES POUR LLM
|
|
||||||
|
|
||||||
### Ce que LLM peut créer/modifier sans code C++ :
|
|
||||||
|
|
||||||
**Entities**
|
|
||||||
- ✅ Wagons (YAML) : stats, composants, visuel
|
|
||||||
- ✅ Drones (YAML) : types, capacités
|
|
||||||
- ✅ Commandants (YAML) : skills, personnalité
|
|
||||||
- ✅ Missions (YAML) : events, choix, rewards
|
|
||||||
|
|
||||||
**UI**
|
|
||||||
- ✅ Screens (JSON) : layouts, elements
|
|
||||||
- ✅ Widgets (JSON) : gauges, panels, text
|
|
||||||
- ✅ Themes (JSON) : colors, fonts, styles
|
|
||||||
|
|
||||||
**Content**
|
|
||||||
- ✅ Dialogues (YAML)
|
|
||||||
- ✅ Events (YAML)
|
|
||||||
- ✅ Story beats (YAML)
|
|
||||||
- ✅ Balance values (TOML)
|
|
||||||
|
|
||||||
**Assets**
|
|
||||||
- ✅ Manifests (TOML) : sprites metadata
|
|
||||||
- ✅ Tags, categories, filters
|
|
||||||
- ✅ Asset relationships
|
|
||||||
|
|
||||||
### Workflow LLM
|
|
||||||
|
|
||||||
**Exemple : "Créer un nouveau wagon blindé lourd"**
|
|
||||||
|
|
||||||
1. LLM crée `entities/wagons/wagon_heavy_armored.yaml`
|
|
||||||
2. LLM met à jour `assets/sprites/wagons.manifest` (nouveau sprite)
|
|
||||||
3. LLM peut tester en modifiant une mission pour donner ce wagon
|
|
||||||
4. **Aucun code C++ touché**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## QUESTIONS OUVERTES
|
|
||||||
|
|
||||||
### Architecture
|
|
||||||
|
|
||||||
1. **Scripting Lua ou config-only ?**
|
|
||||||
- Lua = plus flexible pour game logic
|
|
||||||
- Config = plus simple, assez pour events/missions
|
|
||||||
- **Décision** : À trancher selon complexité game logic
|
|
||||||
|
|
||||||
2. **Save system format ?**
|
|
||||||
- JSON (human-readable, LLM-friendly)
|
|
||||||
- Binaire (compact, rapide)
|
|
||||||
- **Recommandation** : JSON pour dev, option binaire pour release
|
|
||||||
|
|
||||||
3. **Networking futur ?**
|
|
||||||
- Pokrovsk = solo only
|
|
||||||
- Autres projets ?
|
|
||||||
- **Impact** : Architecture ECS doit supporter network sync ou pas
|
|
||||||
|
|
||||||
### Performance
|
|
||||||
|
|
||||||
4. **Sprite batching strategy ?**
|
|
||||||
- Batch par texture (standard)
|
|
||||||
- Batch par layer (z-order)
|
|
||||||
- **Décision** : Tester performance avec prototype
|
|
||||||
|
|
||||||
5. **Entity pooling ?**
|
|
||||||
- Object pooling pour éviter alloc/dealloc
|
|
||||||
- Critical pour drones (100+ entities)
|
|
||||||
- **Recommandation** : Oui, implement dès Phase 3
|
|
||||||
|
|
||||||
### Tooling
|
|
||||||
|
|
||||||
6. **Level editor ?**
|
|
||||||
- ImGui-based editor in-engine
|
|
||||||
- Externe (web-based ?)
|
|
||||||
- **Recommandation** : ImGui in-engine = plus rapide
|
|
||||||
|
|
||||||
7. **Asset hot-reload ?**
|
|
||||||
- Reload YAML/JSON/textures sans restart
|
|
||||||
- Crucial pour iteration rapide
|
|
||||||
- **Recommandation** : Oui, implement Phase 2-3
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## DÉPENDANCES EXTERNES
|
|
||||||
|
|
||||||
### Obligatoires
|
|
||||||
- **bgfx** : Rendering (https://github.com/bkaradzic/bgfx)
|
|
||||||
- **bx** : Base library pour bgfx (https://github.com/bkaradzic/bx)
|
|
||||||
- **bimg** : Image loading pour bgfx (https://github.com/bkaradzic/bimg)
|
|
||||||
- **SDL2** : Windowing + input (https://www.libsdl.org/)
|
|
||||||
- **yaml-cpp** : YAML parsing (https://github.com/jbeder/yaml-cpp)
|
|
||||||
- **nlohmann/json** : JSON parsing (https://github.com/nlohmann/json)
|
|
||||||
- **stb_image** : Image loading (https://github.com/nothings/stb)
|
|
||||||
|
|
||||||
### Optionnelles
|
|
||||||
- **TOML++** : TOML parsing (https://github.com/marzer/tomlplusplus)
|
|
||||||
- **ImGui** : Debug UI (https://github.com/ocornut/imgui)
|
|
||||||
- **Lua** : Scripting (https://www.lua.org/)
|
|
||||||
- **stb_truetype** : Font rendering (https://github.com/nothings/stb)
|
|
||||||
- **FreeType** : Alternative font rendering (https://freetype.org/)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## RISQUES & MITIGATION
|
|
||||||
|
|
||||||
| Risque | Impact | Probabilité | Mitigation |
|
|
||||||
|--------|--------|-------------|------------|
|
|
||||||
| bgfx trop complexe | HAUT | MOYEN | Exemples officiels, communauté active |
|
|
||||||
| Scope creep framework | HAUT | HAUT | Lock features après Phase 4, focus prototype |
|
|
||||||
| Performance 2D insuffisante | MOYEN | FAIBLE | Batching + profiling dès Phase 2 |
|
|
||||||
| Config system trop rigide | MOYEN | MOYEN | Itérer avec prototype Pokrovsk |
|
|
||||||
| LLM-generated content bugs | MOYEN | MOYEN | Validation schema (JSON schema, YAML schema) |
|
|
||||||
| Timeline trop optimiste | HAUT | MOYEN | Buffers 20% par phase |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## RÉFÉRENCES
|
|
||||||
|
|
||||||
### bgfx
|
|
||||||
- Repo officiel : https://github.com/bkaradzic/bgfx
|
|
||||||
- Documentation : https://bkaradzic.github.io/bgfx/
|
|
||||||
- Exemples : https://github.com/bkaradzic/bgfx/tree/master/examples
|
|
||||||
|
|
||||||
### Architecture ECS
|
|
||||||
- "Overwatch Gameplay Architecture" (GDC Talk)
|
|
||||||
- "Data-Oriented Design" (Richard Fabian)
|
|
||||||
|
|
||||||
### 2D Rendering bgfx
|
|
||||||
- bgfx example-26 (vectordisplay)
|
|
||||||
- NanoVG-bgfx (https://github.com/memononen/nanovg)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## NEXT STEPS
|
|
||||||
|
|
||||||
1. **Setup projet** : Créer repo GroveEngine, structure folders
|
|
||||||
2. **Intégrer bgfx** : Submodules + build
|
|
||||||
3. **Hello Triangle** : Première fenêtre + rendering
|
|
||||||
4. **Suivre plan Phase 1** : 4 semaines pour core engine
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Document Version** : 1.0
|
|
||||||
**Status** : Architecture Design
|
|
||||||
**Owner** : Alexis
|
|
||||||
**Related** : `Projects/CONCEPT/pokrovsk_iron_line_v2.md`
|
|
||||||
2209
Projects/WIP/wechat_miniapp_homework.md
Normal file
@ -1 +1 @@
|
|||||||
{"streak": 2, "last_check_date": "2025-11-25", "days_skipped": 0, "last_skip_date": "2025-11-19"}
|
{"streak": 2, "last_check_date": "2025-11-25", "days_skipped": 1, "last_skip_date": "2025-11-25"}
|
||||||
@ -853,3 +853,25 @@ Bon retour après 2 jours d'absence. Montre une meilleure compréhension des con
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### 2025-11-25 15:00
|
||||||
|
|
||||||
|
**Triggered by** : TTS Service
|
||||||
|
**Check Time** : 14:00
|
||||||
|
**Status** : max_retries
|
||||||
|
**Streak** : 2 jours
|
||||||
|
**Days Skipped** : 1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### 2025-11-25 17:00
|
||||||
|
|
||||||
|
**Triggered by** : TTS Service
|
||||||
|
**Check Time** : 16:00
|
||||||
|
**Status** : max_retries
|
||||||
|
**Streak** : 2 jours
|
||||||
|
**Days Skipped** : 1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|||||||
99
checklists/Pre_Departure_Checklist.md
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
# PRE-DEPARTURE CHECKLIST
|
||||||
|
|
||||||
|
<table style="width:100%; font-size:0.8em; line-height:1.2;">
|
||||||
|
<tr valign="top">
|
||||||
|
<td width="50%" style="padding-right:10px;">
|
||||||
|
|
||||||
|
**TECH** | A | T
|
||||||
|
---|---|---
|
||||||
|
Phone | □ | □
|
||||||
|
Phone charger | □ | □
|
||||||
|
Powerbank | □ | □
|
||||||
|
Laptop | □ | □
|
||||||
|
Laptop charger | □ | □
|
||||||
|
Earbuds | □ | □
|
||||||
|
Cables | □ | □
|
||||||
|
|
||||||
|
**ESSENTIALS** | A | T
|
||||||
|
---|---|---
|
||||||
|
Wallet | □ | □
|
||||||
|
Cash | □ | □
|
||||||
|
Cards | □ | □
|
||||||
|
Keys - Car | □ | □
|
||||||
|
Keys - Apt | □ | □
|
||||||
|
ID/Passport | □ | □
|
||||||
|
Papers | □ | □
|
||||||
|
|
||||||
|
**PERSONAL** | A | T
|
||||||
|
---|---|---
|
||||||
|
Watch | □ | □
|
||||||
|
Jewelry | □ | □
|
||||||
|
Glasses | □ | □
|
||||||
|
Contacts + solution | □ | □
|
||||||
|
|
||||||
|
**COMFORT** | A | T
|
||||||
|
---|---|---
|
||||||
|
Water | □ | □
|
||||||
|
Food | □ | □
|
||||||
|
Snacks | □ | □
|
||||||
|
Cigarettes | □ | □
|
||||||
|
Lighter | □ | □
|
||||||
|
Gum/Mints | □ | □
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td width="50%" style="padding-left:10px;">
|
||||||
|
|
||||||
|
**HYGIENE & HEALTH** | A | T
|
||||||
|
---|---|---
|
||||||
|
Tissues | □ | □
|
||||||
|
Sanitizer | □ | □
|
||||||
|
Sanitary pads | □ | □
|
||||||
|
Medications | □ | □
|
||||||
|
Deodorant | □ | □
|
||||||
|
Sunscreen | □ | □
|
||||||
|
Lip balm | □ | □
|
||||||
|
|
||||||
|
**WEATHER** | A | T
|
||||||
|
---|---|---
|
||||||
|
Umbrella | □ | □
|
||||||
|
Jacket | □ | □
|
||||||
|
Sunglasses | □ | □
|
||||||
|
Scarf | □ | □
|
||||||
|
Hat | □ | □
|
||||||
|
|
||||||
|
**TRIP/OVERNIGHT** | A | T
|
||||||
|
---|---|---
|
||||||
|
Toiletries bag | □ | □
|
||||||
|
Toothbrush/paste | □ | □
|
||||||
|
Shower essentials | □ | □
|
||||||
|
Clothes change | □ | □
|
||||||
|
Underwear | □ | □
|
||||||
|
Socks | □ | □
|
||||||
|
Pajamas | □ | □
|
||||||
|
Towel | □ | □
|
||||||
|
|
||||||
|
**WORK** | A | T
|
||||||
|
---|---|---
|
||||||
|
Notebook | □ | □
|
||||||
|
Pens | □ | □
|
||||||
|
Business cards | □ | □
|
||||||
|
USB | □ | □
|
||||||
|
|
||||||
|
**SOCIAL/DATE** | A | T
|
||||||
|
---|---|---
|
||||||
|
Gift | □ | □
|
||||||
|
Perfume | □ | □
|
||||||
|
|
||||||
|
**MENTAL PREP** | A | T
|
||||||
|
---|---|---
|
||||||
|
Mood check | □ | □
|
||||||
|
Destination OK | □ | □
|
||||||
|
Transport OK | □ | □
|
||||||
|
Timing clear | □ | □
|
||||||
|
Intentions set | □ | □
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
**A** = Alexis | **T** = Tingting • *Print & check before departure*
|
||||||
BIN
checklists/Pre_Departure_Checklist.pdf
Normal file
147
couple_backlog/29_novembre_2025_hopital.md
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
# 29 Novembre 2025 - Incident Hôpital
|
||||||
|
|
||||||
|
**Date** : 29 novembre 2025
|
||||||
|
**Type** : Quasi-conflit désamorcé
|
||||||
|
**Contexte** : Hôpital + Faim + Date restaurant italien
|
||||||
|
**Outcome** : Positif (désamorçage réussi + belle soirée)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contexte
|
||||||
|
|
||||||
|
### Situation
|
||||||
|
- Tingting à l'hôpital pour examen médical
|
||||||
|
- Examen requiert jeûne (pas de nourriture depuis longtemps)
|
||||||
|
- Alexis l'accompagne
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Incident
|
||||||
|
|
||||||
|
### Déclenchement
|
||||||
|
- Tingting pas mangé → Irritabilité
|
||||||
|
- Début d'échange tendu entre Alexis et Tingting
|
||||||
|
- Failli se disputer
|
||||||
|
|
||||||
|
### Pattern observé d'Alexis
|
||||||
|
- **Incapable de la calmer** quand elle énervée
|
||||||
|
- **Focus 100% sur ses émotions** (pas sur résolution problème)
|
||||||
|
- **Besoin qu'elle soit calme** pour pouvoir être rationnel
|
||||||
|
|
||||||
|
### Désamorçage (SUCCESS)
|
||||||
|
- **Alexis arrête l'échange**
|
||||||
|
- Ne cherche pas à "résoudre" ou "calmer"
|
||||||
|
- Se retire de la situation
|
||||||
|
→ **Situation s'arrange d'elle-même**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Révélation Clé
|
||||||
|
|
||||||
|
### Une fois Tingting mangé
|
||||||
|
- **Humeur s'améliore drastiquement**
|
||||||
|
- Retour à un état émotionnel normal
|
||||||
|
- Pas de conflit résiduel
|
||||||
|
|
||||||
|
**Leçon** : **Besoins physiques (faim) > Gestion émotionnelle**
|
||||||
|
|
||||||
|
Quand quelqu'un a faim/sommeil/douleur physique :
|
||||||
|
- ✅ Adresser le besoin physique FIRST
|
||||||
|
- ❌ Essayer de "gérer émotionnellement" avant
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Date Restaurant Italien (Même Soir)
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
- Alexis avait prévu date restaurant italien
|
||||||
|
- Alexis personnellement **très happy** d'y aller
|
||||||
|
|
||||||
|
### Contagion Émotionnelle Positive
|
||||||
|
- **Happiness d'Alexis "contamine" Tingting**
|
||||||
|
- Elle beaucoup mieux pendant le repas
|
||||||
|
- Belle soirée malgré incident hôpital
|
||||||
|
|
||||||
|
**Leçon** : **L'énergie positive d'Alexis peut influencer l'humeur de Tingting**
|
||||||
|
|
||||||
|
Quand Alexis est genuinely happy/excité :
|
||||||
|
- Son énergie est contagieuse
|
||||||
|
- Tingting y répond positivement
|
||||||
|
- Meilleur résultat que "essayer de la rendre heureuse" activement
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Patterns Confirmés
|
||||||
|
|
||||||
|
### 1. Se Retirer > Insister
|
||||||
|
**Quand elle énervée** :
|
||||||
|
- ✅ Arrêter l'échange
|
||||||
|
- ✅ Laisser espace
|
||||||
|
- ✅ Attendre qu'elle se calme
|
||||||
|
- ❌ Essayer de "résoudre" immédiatement
|
||||||
|
- ❌ Chercher à "la calmer"
|
||||||
|
|
||||||
|
**Déjà identifié** : Process de résolution de conflit (22 oct 2025)
|
||||||
|
- Alexis besoin qu'elle soit calme pour être rationnel
|
||||||
|
- Focus sur ses émotions quand elle en colère → Bloque résolution
|
||||||
|
|
||||||
|
**Aujourd'hui prouvé** : Se retirer fonctionne mieux qu'insister
|
||||||
|
|
||||||
|
### 2. Besoins Physiques First
|
||||||
|
- Faim, sommeil, douleur physique > Gestion émotionnelle
|
||||||
|
- Adresser le besoin concret avant de "parler"
|
||||||
|
- Pattern vu aussi : Mode "larve" d'Alexis quand sommeil raté
|
||||||
|
|
||||||
|
### 3. Contagion Émotionnelle
|
||||||
|
- Happiness genuine d'Alexis → Tingting y répond
|
||||||
|
- Pas besoin de "faire des efforts pour elle"
|
||||||
|
- Juste être authentiquement content/excité suffit
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Actions / Leçons
|
||||||
|
|
||||||
|
### ✅ Ce qui a marché
|
||||||
|
1. **Arrêter l'échange** quand tension monte
|
||||||
|
2. **Laisser manger** avant de gérer quoi que ce soit
|
||||||
|
3. **Être genuinely happy** pour la date → Contagion positive
|
||||||
|
|
||||||
|
### ❌ Ce qui ne marche pas
|
||||||
|
1. Essayer de "la calmer" quand énervée (Alexis incapable)
|
||||||
|
2. Tenter de résoudre émotionnellement avant besoin physique
|
||||||
|
3. Forcer une interaction quand elle pas dans bon état
|
||||||
|
|
||||||
|
### 📝 Pour l'avenir
|
||||||
|
- **Checklist pré-interaction** : Elle a mangé ? Dormé ? Besoin physique OK ?
|
||||||
|
- **Si tension monte** : Se retirer, pas insister
|
||||||
|
- **Pour dates** : Alexis focus sur sa propre happiness → Effet positif sur Tingting
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Comparaison avec Octobre 2025
|
||||||
|
|
||||||
|
### Similitudes
|
||||||
|
- Pattern "incapable de calmer" confirmé
|
||||||
|
- Besoin qu'elle soit dans bon état pour résoudre
|
||||||
|
- Se retirer > Insister
|
||||||
|
|
||||||
|
### Différences
|
||||||
|
- **Octobre** : Conflit majeur, crise, rupture quasi
|
||||||
|
- **Novembre** : Quasi-conflit désamorcé rapidement, belle soirée après
|
||||||
|
|
||||||
|
**Évolution positive** : Alexis identifie pattern + applique stratégie de retrait AVANT escalade
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Status Relation
|
||||||
|
|
||||||
|
**Post-incident** : Aucune rancune, belle soirée
|
||||||
|
|
||||||
|
**Pattern général** :
|
||||||
|
- Relation stabilisée depuis fin octobre
|
||||||
|
- Daily check system actif
|
||||||
|
- Incidents mineurs désamorcés efficacement (comme aujourd'hui)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Tags** : `#conflict-resolution` `#physical-needs` `#retreat-strategy` `#emotional-contagion` `#success`
|
||||||
@ -26,6 +26,7 @@
|
|||||||
- Conception rapide et qualitative
|
- Conception rapide et qualitative
|
||||||
- Difficulté à exécuter ce qui est "intellectuellement résolu"
|
- Difficulté à exécuter ce qui est "intellectuellement résolu"
|
||||||
- Pas de dopamine dans l'exécution pure
|
- Pas de dopamine dans l'exécution pure
|
||||||
|
- **MAIS** : Exec prouvée quand projet activé (102 commits/3 semaines nov 2025)
|
||||||
|
|
||||||
### Origine de l'identité et patterns psychologiques
|
### Origine de l'identité et patterns psychologiques
|
||||||
- **Construction identitaire** : "Quand j'étais enfant personne ne me félicitais. J'ai build mon identité sur l'intel"
|
- **Construction identitaire** : "Quand j'étais enfant personne ne me félicitais. J'ai build mon identité sur l'intel"
|
||||||
@ -100,7 +101,7 @@
|
|||||||
- **Capacité caring prouvée** : Golden Week octobre 2025 - a pris soin de Tingting malgré fatigue/maladie, beaux souvenirs créés
|
- **Capacité caring prouvée** : Golden Week octobre 2025 - a pris soin de Tingting malgré fatigue/maladie, beaux souvenirs créés
|
||||||
- **Respect des boundaries** : Accepte la limite de Tingting sur le contact physique avec autres femmes (apprise pendant Golden Week)
|
- **Respect des boundaries** : Accepte la limite de Tingting sur le contact physique avec autres femmes (apprise pendant Golden Week)
|
||||||
|
|
||||||
#### Conflit 16-22 octobre 2025
|
#### Conflit 16-22 octobre 2025 (Crise majeure)
|
||||||
- **Sommeil fragile** : Problème physiologique réel (lumière/bruit = destruction totale), 6 mois pour s'habituer à dormir avec Tingting
|
- **Sommeil fragile** : Problème physiologique réel (lumière/bruit = destruction totale), 6 mois pour s'habituer à dormir avec Tingting
|
||||||
- **Mode "larve"** : État dysfonctionnel (cerveau à 0%) quand setup sommeil raté, incapable de communiquer clairement
|
- **Mode "larve"** : État dysfonctionnel (cerveau à 0%) quand setup sommeil raté, incapable de communiquer clairement
|
||||||
- **Erreur 18 oct** : Communication floue en mode larve, pas de réassurance émotionnelle → "Why are you so mean?"
|
- **Erreur 18 oct** : Communication floue en mode larve, pas de réassurance émotionnelle → "Why are you so mean?"
|
||||||
@ -111,6 +112,16 @@
|
|||||||
- **Erreur 21 oct** : Mauvais timing (elle fatiguée/stressée), cherche affection quand elle fermée, pointe contradictions en mode confrontation
|
- **Erreur 21 oct** : Mauvais timing (elle fatiguée/stressée), cherche affection quand elle fermée, pointe contradictions en mode confrontation
|
||||||
- **Pattern révélé** : Toujours lui qui initie conversations après conflits, épuisant
|
- **Pattern révélé** : Toujours lui qui initie conversations après conflits, épuisant
|
||||||
- **Incompatibilité potentielle** : Lui calme/rationnel vs Elle besoin manifestations émotionnelles dramatiques
|
- **Incompatibilité potentielle** : Lui calme/rationnel vs Elle besoin manifestations émotionnelles dramatiques
|
||||||
|
- **Outcome** : Stabilisation relation après 22 oct, daily check system mis en place
|
||||||
|
|
||||||
|
#### Incident Hôpital 29 novembre 2025
|
||||||
|
- **Contexte** : Tingting à l'hôpital (examen requis jeûne), pas mangé depuis longtemps
|
||||||
|
- **Quasi-conflit** : Failli se disputer, Alexis incapable de la calmer
|
||||||
|
- **Désamorçage** : Alexis arrête l'échange → Situation s'arrange
|
||||||
|
- **Révélation** : Une fois Tingting mangé → Humeur s'améliore drastiquement
|
||||||
|
- **Date restaurant italien** : Happiness d'Alexis "contamine" Tingting, elle beaucoup mieux pendant repas
|
||||||
|
- **Leçon** : Besoins physiques (faim) > Gestion émotionnelle. Se retirer > Insister quand elle énervée.
|
||||||
|
- **Pattern confirmé** : Alexis focus sur émotions de l'autre quand elle en colère, besoin qu'elle calme avant résoudre
|
||||||
|
|
||||||
### Famille et amis
|
### Famille et amis
|
||||||
|
|
||||||
|
|||||||
165
tools/checklist.html
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<style>
|
||||||
|
@page {
|
||||||
|
size: A4;
|
||||||
|
margin: 15mm;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
font-size: 9pt;
|
||||||
|
line-height: 1.1;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 16pt;
|
||||||
|
margin: 0 0 10px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
.column {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background: #333;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 3px 5px;
|
||||||
|
text-align: left;
|
||||||
|
font-size: 9pt;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
padding: 2px 5px;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
td:nth-child(2), td:nth-child(3), th:nth-child(2), th:nth-child(3) {
|
||||||
|
width: 25px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 8pt;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>PRE-DEPARTURE CHECKLIST</h1>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="column">
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr><th colspan="3">TECH</th></tr>
|
||||||
|
<tr><td>Phone</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Phone charger</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Powerbank</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Laptop</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Laptop charger</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Earbuds</td><td>☐</td><td>☐</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr><th colspan="3">ESSENTIALS</th></tr>
|
||||||
|
<tr><td>Wallet</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Cash</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Cards</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td style="font-size:10pt;font-weight:bold;">KEYS - CAR</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>ID/Passport</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Papers</td><td>☐</td><td>☐</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr><th colspan="3">PERSONAL</th></tr>
|
||||||
|
<tr><td>Watch</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Jewelry</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Glasses</td><td>☐</td><td>☐</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr><th colspan="3">COMFORT</th></tr>
|
||||||
|
<tr><td>Water</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Food</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Snacks</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Clopes</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Briquet</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Mint mouth</td><td>☐</td><td>☐</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr><th colspan="3">HYGIENE & HEALTH</th></tr>
|
||||||
|
<tr><td>Tissues</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Sanitizer</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Sanitary pads</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Medications</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Deodorant</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Sunscreen</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Lip balm</td><td>☐</td><td>☐</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr><th colspan="3">WEATHER</th></tr>
|
||||||
|
<tr><td>Umbrella</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Jacket</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Sunglasses</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Scarf</td><td>☐</td><td>☐</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr><th colspan="3">TRIP/OVERNIGHT</th></tr>
|
||||||
|
<tr><td>Toiletries bag</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Toothbrush/paste</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Shower essentials</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Clothes change</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Underwear</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Socks</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Pajamas</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Towel</td><td>☐</td><td>☐</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr><th colspan="3">WORK</th></tr>
|
||||||
|
<tr><td>Notebook</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Pens</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>USB</td><td>☐</td><td>☐</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr><th colspan="3">SOCIAL/DATE</th></tr>
|
||||||
|
<tr><td>Gift</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Perfume</td><td>☐</td><td>☐</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr><th colspan="3">MENTAL PREP</th></tr>
|
||||||
|
<tr><td>Mood check</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Destination OK</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Transport OK</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Timing clear</td><td>☐</td><td>☐</td></tr>
|
||||||
|
<tr><td>Intentions set</td><td>☐</td><td>☐</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
A = Alexis | T = Tingting
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -1,9 +1,10 @@
|
|||||||
# Topic : Cadeau père de Tingting
|
# Topic : Cadeau père de Tingting
|
||||||
|
|
||||||
**Status** : 🔍 En réflexion
|
**Status** : 🎯 En cours d'exécution
|
||||||
**Date création** : 12 novembre 2025
|
**Date création** : 12 novembre 2025
|
||||||
**Deadline** : 11 décembre 2025 (anniversaire)
|
**Deadline** : 11 décembre 2025 (anniversaire) - **10 jours restants**
|
||||||
**Budget** : ~1000 yuan
|
**Budget** : 700-800 yuan (ajusté pour Chinese New Year)
|
||||||
|
**Dernière mise à jour** : 1er décembre 2025
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -14,129 +15,150 @@
|
|||||||
- Renforcer relation avec belle-famille
|
- Renforcer relation avec belle-famille
|
||||||
- Montrer respect et considération
|
- Montrer respect et considération
|
||||||
- Image gendre attentionné
|
- Image gendre attentionné
|
||||||
|
- **Objectif : "Mother of God" gift - Statement piece mémorable (match niveau aquarium offert à la mère)**
|
||||||
|
|
||||||
**Ce qu'on sait du père de Tingting :**
|
**Ce qu'on sait du père de Tingting :**
|
||||||
- Anniversaire : 11 décembre
|
- Anniversaire : 11 décembre
|
||||||
- Âge : ~57 ans
|
- Âge : ~57 ans
|
||||||
- Profession : Investisseur dans le bâtiment/chantiers (beaucoup de stress)
|
- Profession : Investisseur dans le bâtiment/chantiers (beaucoup de stress)
|
||||||
- Centres d'intérêt : Pêche, networking avec personnes haut placées
|
- Centres d'intérêt : Pêche, networking avec personnes haut placées, **mahjong (possède table automatique)**
|
||||||
- Personnalité : Traditionnel mais ouvert, sociable
|
- Personnalité : Traditionnel mais ouvert, sociable
|
||||||
- Culture / valeurs : Apprécie le prestige/statut social
|
- Culture / valeurs : Apprécie le prestige/statut social
|
||||||
- ⚠️ Éviter alcool : essaie d'arrêter
|
- ⚠️ Éviter alcool : essaie d'arrêter
|
||||||
|
- **Contexte social : Reçoit régulièrement des invités pour repas**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Contraintes et considérations
|
## Décision finale : SET MAHJONG DISPLAY ARTISANAL
|
||||||
|
|
||||||
**Culturelles (Chine) :**
|
**Concept** :
|
||||||
- Éviter cadeaux symboliquement négatifs (horloges, objets blancs/noirs selon contexte, chiffre 4)
|
- Set mahjong niveau collection (pas pour jouer - il a déjà table auto)
|
||||||
- Privilégier : Santé, longévité, prospérité, prestige
|
- Fonction : **Pièce d'art exposée** dans salon/bureau
|
||||||
- Qualité > Quantité (face importante)
|
- Statement piece pour impressionner invités
|
||||||
- Emballage soigné essentiel
|
- Symbolique culture chinoise traditionnelle forte
|
||||||
|
|
||||||
**Pratiques :**
|
**Critères obligatoires** :
|
||||||
- Utilisable / appréciable au quotidien vs décoratif
|
- ✅ Matériaux premium : Bambou gravé, jade, bois précieux (红木), os
|
||||||
- Âge du père (confort, santé, loisirs adaptés)
|
- ✅ Coffret display vitré ou bois massif avec présentation soignée
|
||||||
- Shanghai / climat / mode de vie
|
- ✅ 144 tuiles complètes (set complet traditionnel)
|
||||||
|
- ✅ Artisanal/gravé main si possible (手工雕刻)
|
||||||
|
- ✅ Budget : 700-900 yuan
|
||||||
|
- ✅ Livraison avant 9 décembre (buffer 2 jours)
|
||||||
|
|
||||||
**Relationnelles :**
|
**Pourquoi ce choix** :
|
||||||
- Niveau de proximité actuel avec Alexis
|
- ✅ Match "aquarium energy" (statement piece bold, mémorable, pas safe)
|
||||||
- Image à projeter (gendre sérieux, attentionné, respectueux)
|
- ✅ Compatible table auto (display séparé, pas de conflit)
|
||||||
- Validation par Tingting essentielle
|
- ✅ Symbolique chinoise maximale (prestige culturel)
|
||||||
|
- ✅ Conversation starter avec invités
|
||||||
|
- ✅ Objet collection qui prend de la valeur
|
||||||
|
- ✅ Non-consommable, durable
|
||||||
|
- ✅ Démontre connaissance culture + considération
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Pistes d'idées
|
## Plan d'exécution (Timeline serrée)
|
||||||
|
|
||||||
**Catégorie Santé / Bien-être :**
|
**1er décembre (AUJOURD'HUI)** :
|
||||||
- [ ] Thé haut de gamme (collection qualité, coffret prestige)
|
- ✅ Décision prise : Set mahjong display
|
||||||
- [ ] Accessoires santé (masseur, coussin ergonomique)
|
- 🔄 Recherche Taobao avec termes chinois
|
||||||
- [ ] Supplément traditionnel chinois haut de gamme (ginseng, etc.)
|
|
||||||
|
|
||||||
**Catégorie Culture / Loisirs :**
|
**2 décembre** :
|
||||||
- [ ] Calligraphie (matériel qualité si pratique)
|
- Commander si bon listing trouvé (vérifier délai livraison Shanghai)
|
||||||
- [ ] Livre collection / édition spéciale
|
- OU Achat physique Yu Garden/Dongtai Road si timing Taobao risqué
|
||||||
- [ ] Équipement hobby spécifique (à identifier)
|
|
||||||
|
|
||||||
**Catégorie Prestige / Symbolique :**
|
**3-8 décembre** :
|
||||||
- [ ] Alcool prestigieux (baijiu qualité, cognac)
|
- Livraison/réception
|
||||||
- [ ] Objet décoratif traditionnel (jade, porcelaine)
|
- Vérification qualité
|
||||||
- [ ] Accessoire luxe quotidien (stylo, accessoire cuir)
|
|
||||||
|
|
||||||
**Catégorie Pratique / Confort :**
|
**9 décembre** :
|
||||||
- [ ] Vêtement qualité (matière premium)
|
- Emballage cadeau premium soigné
|
||||||
- [ ] Accessoire tech adapté seniors (si intérêt)
|
- Préparation présentation
|
||||||
- [ ] Objet confort maison
|
|
||||||
|
**11 décembre** :
|
||||||
|
- Remise cadeau anniversaire
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Informations à obtenir de Tingting
|
## Recherche Taobao - Termes chinois
|
||||||
|
|
||||||
**Questions à poser :**
|
**Recherches principales** :
|
||||||
|
```
|
||||||
|
麻将牌收藏级 实木盒
|
||||||
|
(Set mahjong collection + coffret bois massif)
|
||||||
|
|
||||||
1. **Contexte du cadeau**
|
竹制麻将 收藏 礼盒
|
||||||
- C'est pour quelle occasion ? (anniversaire, fête, geste général)
|
(Mahjong bambou collection coffret cadeau)
|
||||||
- Deadline ?
|
|
||||||
- Budget approprié selon contexte ?
|
|
||||||
|
|
||||||
2. **Profil du père**
|
玉石麻将 高档 展示盒
|
||||||
- Qu'est-ce qu'il aime faire au quotidien ?
|
(Mahjong jade haut de gamme boîte display)
|
||||||
- Quels sont ses hobbies / passions ?
|
|
||||||
- Qu'est-ce qu'il possède déjà qu'il apprécie beaucoup ?
|
|
||||||
- Santé / limitations physiques à considérer ?
|
|
||||||
|
|
||||||
3. **Préférences / Style**
|
红木麻将 礼品装
|
||||||
- Plutôt pratique ou symbolique ?
|
(Mahjong bois précieux emballage cadeau)
|
||||||
- Plutôt traditionnel ou moderne ?
|
|
||||||
- Qu'est-ce qui lui fait vraiment plaisir d'habitude ?
|
|
||||||
|
|
||||||
4. **Contexte familial**
|
手工雕刻麻将 收藏套装
|
||||||
- Qu'est-ce que d'autres membres de la famille ont offert qui a bien marché ?
|
(Mahjong gravé main set collection)
|
||||||
- Y a-t-il des attentes implicites ?
|
|
||||||
- Comment il réagit aux cadeaux généralement ?
|
|
||||||
|
|
||||||
5. **Validation**
|
传统工艺麻将 高端礼盒
|
||||||
- Tingting a-t-elle des suggestions initiales ?
|
(Mahjong artisanat traditionnel coffret haut gamme)
|
||||||
- Qu'est-ce qui serait vraiment apprécié selon elle ?
|
```
|
||||||
- Qu'est-ce qui serait maladroit ou à éviter absolument ?
|
|
||||||
|
**Mots-clés positifs à chercher** :
|
||||||
|
- 收藏级 (niveau collection)
|
||||||
|
- 高档 (haut de gamme)
|
||||||
|
- 礼品装 (emballage cadeau)
|
||||||
|
- 实木 (bois massif)
|
||||||
|
- 手工 (fait main)
|
||||||
|
- 红木 (bois précieux)
|
||||||
|
- 展示盒 (boîte d'exposition)
|
||||||
|
|
||||||
|
**Mots-clés à éviter** :
|
||||||
|
- 便携 (portable/voyage)
|
||||||
|
- 自动 (automatique)
|
||||||
|
- 塑料 (plastique)
|
||||||
|
- 预售 (pré-vente)
|
||||||
|
|
||||||
|
**Filtres critiques** :
|
||||||
|
- Prix : 700-900 yuan
|
||||||
|
- Priorité : 上海发货 (expédition Shanghai = 1-3 jours)
|
||||||
|
- Éviter : 定制 (customisé = délai trop long)
|
||||||
|
- Vérifier : 144块 (144 pièces = set complet)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Backup plan si Taobao timing risqué
|
||||||
|
|
||||||
|
**Achat physique Shanghai (2 décembre)** :
|
||||||
|
- **Yu Garden 豫园** (City God Temple) : Artisanat traditionnel
|
||||||
|
- **Dongtai Road 东台路** : Marché antiquités
|
||||||
|
- **Tianzifang 田子坊** : Artisan stores
|
||||||
|
|
||||||
|
**Phrase utile** :
|
||||||
|
`有收藏级的麻将套装吗?` (Vous avez des sets mahjong niveau collection ?)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Options alternatives considérées (rejetées)
|
||||||
|
|
||||||
|
- ❌ Bonsaï mature : Bon statement mais nécessite entretien
|
||||||
|
- ❌ Terrarium écosystème : Trop moderne, moins symbolique chinoise
|
||||||
|
- ❌ Kit cocktails : Conflit avec évitement alcool
|
||||||
|
- ❌ Service thé Yixing : Bon mais moins bold que mahjong
|
||||||
|
- ❌ Plateau service bois : Trop safe
|
||||||
|
- ❌ Baijiu premium : Conflit évitement alcool
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Critères de décision finale
|
## Critères de décision finale
|
||||||
|
|
||||||
**Le cadeau idéal devra :**
|
**Le cadeau idéal devra :**
|
||||||
- ✅ Être culturellement approprié (pas de symbole négatif)
|
- ✅ Être culturellement approprié (mahjong = symbolique forte)
|
||||||
- ✅ Correspondre au budget / contexte (ni trop ni pas assez)
|
- ✅ Correspondre au budget (700-800 yuan)
|
||||||
- ✅ Montrer considération / attention (pas générique)
|
- ✅ Montrer considération / attention (artisanal, pas générique)
|
||||||
- ✅ Être validé par Tingting (elle connaît son père)
|
- ✅ Qualité visible (matériaux premium, coffret soigné)
|
||||||
- ✅ Qualité visible (emballage inclus)
|
- ✅ Statement piece mémorable (match aquarium)
|
||||||
- ✅ Utilisable / appréciable réellement
|
- ✅ Non-consommable, durable
|
||||||
|
- ✅ Livrable avant deadline
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Next steps
|
**Date dernière mise à jour** : 1er décembre 2025
|
||||||
|
|
||||||
**☐ Discussion avec Tingting**
|
|
||||||
- Répondre aux questions ci-dessus
|
|
||||||
- Comprendre occasion et contexte
|
|
||||||
- Budget approprié
|
|
||||||
|
|
||||||
**☐ Shortlist 2-3 options**
|
|
||||||
- Basé sur infos obtenues
|
|
||||||
- Rechercher qualité / prix
|
|
||||||
|
|
||||||
**☐ Validation finale Tingting**
|
|
||||||
- Présenter options avec rationale
|
|
||||||
- Choix ensemble
|
|
||||||
|
|
||||||
**☐ Achat + Emballage soigné**
|
|
||||||
- Acheter en avance (pas last minute)
|
|
||||||
- Emballage approprié culturellement
|
|
||||||
|
|
||||||
**☐ Préparation présentation**
|
|
||||||
- Quelques mots à dire en chinois ?
|
|
||||||
- Timing de remise
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Date dernière mise à jour** : 12 novembre 2025
|
|
||||||
|
|||||||
BIN
work_chinese/PPT04122025/Images/CarteCNNice.jpg
Normal file
|
After Width: | Height: | Size: 285 KiB |
BIN
work_chinese/PPT04122025/Images/CarteENTravers.jpg
Normal file
|
After Width: | Height: | Size: 291 KiB |
BIN
work_chinese/PPT04122025/Images/FicheResto.png
Normal file
|
After Width: | Height: | Size: 509 KiB |
BIN
work_chinese/PPT04122025/Images/Images.zip
Normal file
BIN
work_chinese/PPT04122025/Images/InsideResto.jpg
Normal file
|
After Width: | Height: | Size: 418 KiB |
BIN
work_chinese/PPT04122025/Images/LayoutTable.jpg
Normal file
|
After Width: | Height: | Size: 346 KiB |
BIN
work_chinese/PPT04122025/Images/OutsideResto.jpg
Normal file
|
After Width: | Height: | Size: 366 KiB |
BIN
work_chinese/PPT04122025/Images/PICCOLO 组合早餐.jpg
Normal file
|
After Width: | Height: | Size: 338 KiB |
BIN
work_chinese/PPT04122025/Images/炸鳕鱼球.jpg
Normal file
|
After Width: | Height: | Size: 113 KiB |
530
work_chinese/PPT04122025/_build/alimentari_piccolo.html
Normal file
@ -0,0 +1,530 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<style>
|
||||||
|
html { background: #ffffff; }
|
||||||
|
body {
|
||||||
|
width: 720pt;
|
||||||
|
height: 405pt;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
color: #2C2C2C;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide {
|
||||||
|
width: 720pt;
|
||||||
|
height: 405pt;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
page-break-after: always;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Slide 1 - Title */
|
||||||
|
.slide-1 {
|
||||||
|
background: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-stripe-top {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 20pt;
|
||||||
|
background: #009246;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-stripe-mid {
|
||||||
|
position: absolute;
|
||||||
|
top: 20pt;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 20pt;
|
||||||
|
background: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-stripe-bot {
|
||||||
|
position: absolute;
|
||||||
|
top: 40pt;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 20pt;
|
||||||
|
background: #CE2B37;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-container {
|
||||||
|
position: absolute;
|
||||||
|
top: 95pt;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background: #F8F8F8;
|
||||||
|
padding: 28pt 45pt;
|
||||||
|
border-radius: 15pt;
|
||||||
|
box-shadow: 0 8pt 25pt rgba(0, 0, 0, 0.15);
|
||||||
|
border: 3pt solid #D4AF37;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-main {
|
||||||
|
font-size: 44pt;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #009246;
|
||||||
|
margin-bottom: 12pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-sub {
|
||||||
|
font-size: 26pt;
|
||||||
|
color: #CE2B37;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 8pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-tag {
|
||||||
|
font-size: 16pt;
|
||||||
|
color: #666666;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Slide 2 - Location */
|
||||||
|
.slide-2 {
|
||||||
|
background: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-green {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 60pt;
|
||||||
|
background: #009246;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-text {
|
||||||
|
position: absolute;
|
||||||
|
top: 12pt;
|
||||||
|
left: 35pt;
|
||||||
|
font-size: 32pt;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box-1 {
|
||||||
|
position: absolute;
|
||||||
|
top: 80pt;
|
||||||
|
left: 30pt;
|
||||||
|
width: 300pt;
|
||||||
|
background: #F8F8F8;
|
||||||
|
border-radius: 10pt;
|
||||||
|
padding: 15pt;
|
||||||
|
border-left: 5pt solid #009246;
|
||||||
|
box-shadow: 0 3pt 10pt rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box-2 {
|
||||||
|
position: absolute;
|
||||||
|
top: 80pt;
|
||||||
|
right: 30pt;
|
||||||
|
width: 300pt;
|
||||||
|
background: #F8F8F8;
|
||||||
|
border-radius: 10pt;
|
||||||
|
padding: 15pt;
|
||||||
|
border-left: 5pt solid #009246;
|
||||||
|
box-shadow: 0 3pt 10pt rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box-3 {
|
||||||
|
position: absolute;
|
||||||
|
top: 185pt;
|
||||||
|
left: 30pt;
|
||||||
|
width: 300pt;
|
||||||
|
background: #F8F8F8;
|
||||||
|
border-radius: 10pt;
|
||||||
|
padding: 15pt;
|
||||||
|
border-left: 5pt solid #009246;
|
||||||
|
box-shadow: 0 3pt 10pt rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box-4 {
|
||||||
|
position: absolute;
|
||||||
|
top: 185pt;
|
||||||
|
right: 30pt;
|
||||||
|
width: 300pt;
|
||||||
|
background: #F8F8F8;
|
||||||
|
border-radius: 10pt;
|
||||||
|
padding: 15pt;
|
||||||
|
border-left: 5pt solid #009246;
|
||||||
|
box-shadow: 0 3pt 10pt rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-title {
|
||||||
|
font-size: 16pt;
|
||||||
|
color: #CE2B37;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 6pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-text {
|
||||||
|
font-size: 19pt;
|
||||||
|
color: #2C2C2C;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.star-gold {
|
||||||
|
color: #D4AF37;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-bottom {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 20pt;
|
||||||
|
left: 30pt;
|
||||||
|
right: 30pt;
|
||||||
|
height: 90pt;
|
||||||
|
border-radius: 10pt;
|
||||||
|
box-shadow: 0 4pt 15pt rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Slide 3 & 4 - Dishes */
|
||||||
|
.slide-dish {
|
||||||
|
background: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dish-photo-section {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 400pt;
|
||||||
|
height: 405pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dish-photo {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dish-details-section {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 320pt;
|
||||||
|
height: 405pt;
|
||||||
|
background: #F8F8F8;
|
||||||
|
border-left: 6pt solid #009246;
|
||||||
|
padding: 45pt 25pt 90pt 25pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dish-label {
|
||||||
|
font-size: 14pt;
|
||||||
|
color: #CE2B37;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 7pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dish-title {
|
||||||
|
font-size: 27pt;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #009246;
|
||||||
|
margin-bottom: 12pt;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keyword-item {
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding: 6pt 11pt;
|
||||||
|
border-radius: 6pt;
|
||||||
|
border-left: 3pt solid #D4AF37;
|
||||||
|
box-shadow: 0 2pt 5pt rgba(0, 0, 0, 0.06);
|
||||||
|
margin-bottom: 7pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keyword-txt {
|
||||||
|
font-size: 14pt;
|
||||||
|
color: #2C2C2C;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-badge {
|
||||||
|
background: #009246;
|
||||||
|
padding: 8pt 15pt;
|
||||||
|
border-radius: 8pt;
|
||||||
|
display: inline-block;
|
||||||
|
box-shadow: 0 3pt 10pt rgba(0, 146, 70, 0.25);
|
||||||
|
margin-top: 10pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-val {
|
||||||
|
font-size: 20pt;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Slide 5 - Evaluation */
|
||||||
|
.slide-5 {
|
||||||
|
background: #F8F8F8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eval-head {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 55pt;
|
||||||
|
background: #CE2B37;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eval-head-txt {
|
||||||
|
position: absolute;
|
||||||
|
top: 10pt;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
font-size: 34pt;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #FFFFFF;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eval-item-1 {
|
||||||
|
position: absolute;
|
||||||
|
top: 75pt;
|
||||||
|
left: 30pt;
|
||||||
|
width: 310pt;
|
||||||
|
height: 90pt;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 10pt;
|
||||||
|
padding: 12pt;
|
||||||
|
box-shadow: 0 4pt 12pt rgba(0, 0, 0, 0.08);
|
||||||
|
border-top: 5pt solid #D4AF37;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eval-item-2 {
|
||||||
|
position: absolute;
|
||||||
|
top: 75pt;
|
||||||
|
right: 30pt;
|
||||||
|
width: 310pt;
|
||||||
|
height: 90pt;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 10pt;
|
||||||
|
padding: 12pt;
|
||||||
|
box-shadow: 0 4pt 12pt rgba(0, 0, 0, 0.08);
|
||||||
|
border-top: 5pt solid #D4AF37;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eval-item-3 {
|
||||||
|
position: absolute;
|
||||||
|
top: 185pt;
|
||||||
|
left: 30pt;
|
||||||
|
width: 310pt;
|
||||||
|
height: 90pt;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 10pt;
|
||||||
|
padding: 12pt;
|
||||||
|
box-shadow: 0 4pt 12pt rgba(0, 0, 0, 0.08);
|
||||||
|
border-top: 5pt solid #D4AF37;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eval-item-4 {
|
||||||
|
position: absolute;
|
||||||
|
top: 185pt;
|
||||||
|
right: 30pt;
|
||||||
|
width: 310pt;
|
||||||
|
height: 90pt;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 10pt;
|
||||||
|
padding: 12pt;
|
||||||
|
box-shadow: 0 4pt 12pt rgba(0, 0, 0, 0.08);
|
||||||
|
border-top: 5pt solid #D4AF37;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eval-label {
|
||||||
|
font-size: 18pt;
|
||||||
|
color: #CE2B37;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 8pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eval-value {
|
||||||
|
font-size: 24pt;
|
||||||
|
color: #009246;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 4pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eval-detail {
|
||||||
|
font-size: 15pt;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.final-box {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 62pt;
|
||||||
|
left: 30pt;
|
||||||
|
right: 30pt;
|
||||||
|
height: 46pt;
|
||||||
|
background: #009246;
|
||||||
|
border-radius: 10pt;
|
||||||
|
box-shadow: 0 4pt 15pt rgba(0, 146, 70, 0.25);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.final-msg {
|
||||||
|
font-size: 20pt;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-weight: 700;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-badge {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 15pt;
|
||||||
|
right: 15pt;
|
||||||
|
width: 40pt;
|
||||||
|
height: 40pt;
|
||||||
|
border-radius: 5pt;
|
||||||
|
box-shadow: 0 2pt 6pt rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-green { background: #009246; }
|
||||||
|
.badge-white { background: #FFFFFF; border: 2pt solid #D4AF37; }
|
||||||
|
.badge-red { background: #CE2B37; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- Slide 1: Title -->
|
||||||
|
<div class="slide slide-1">
|
||||||
|
<div class="flag-stripe-top"></div>
|
||||||
|
<div class="flag-stripe-mid"></div>
|
||||||
|
<div class="flag-stripe-bot"></div>
|
||||||
|
|
||||||
|
<div class="title-container">
|
||||||
|
<p class="title-main">Alimentari Piccolo</p>
|
||||||
|
<p class="title-sub">意大利餐吧 & 披萨</p>
|
||||||
|
<p class="title-tag">上海番禺路店</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flag-badge badge-green"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 2: Location & Ambiance -->
|
||||||
|
<div class="slide slide-2">
|
||||||
|
<div class="header-green"></div>
|
||||||
|
<p class="header-text">餐厅概况 | RISTORANTE</p>
|
||||||
|
|
||||||
|
<div class="info-box-1">
|
||||||
|
<p class="info-title">📍 位置</p>
|
||||||
|
<p class="info-text">番禺路390号103室A区</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-box-2">
|
||||||
|
<p class="info-title">🍝 类型</p>
|
||||||
|
<p class="info-text">正宗意大利料理</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-box-3">
|
||||||
|
<p class="info-title">🌟 评分</p>
|
||||||
|
<p class="info-text"><span class="star-gold">★★★★</span> 4.4/5 (3511条)</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-box-4">
|
||||||
|
<p class="info-title">💰 人均</p>
|
||||||
|
<p class="info-text" style="color: #D4AF37;">¥136/人</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<img src="outside.jpg" class="image-bottom" alt="Restaurant">
|
||||||
|
|
||||||
|
<div class="flag-badge badge-red"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 3: Dish 1 - Piadina -->
|
||||||
|
<div class="slide slide-dish">
|
||||||
|
<div class="dish-photo-section">
|
||||||
|
<img src="plat1.jpg" class="dish-photo" alt="Piadina">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="dish-details-section">
|
||||||
|
<p class="dish-label">推荐菜品 #1 | ¥65-75</p>
|
||||||
|
<p class="dish-title">意式皮亚迪纳<br>Piadina</p>
|
||||||
|
|
||||||
|
<div class="keyword-item">
|
||||||
|
<p class="keyword-txt">🔥 现烤薄饼 金黄酥脆</p>
|
||||||
|
</div>
|
||||||
|
<div class="keyword-item">
|
||||||
|
<p class="keyword-txt">🥗 新鲜蔬菜 色彩缤纷</p>
|
||||||
|
</div>
|
||||||
|
<div class="keyword-item">
|
||||||
|
<p class="keyword-txt">🥓 意式火腿 奶酪酱汁</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flag-badge badge-green"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 4: Dish 2 - Croquettes -->
|
||||||
|
<div class="slide slide-dish">
|
||||||
|
<div class="dish-photo-section">
|
||||||
|
<img src="plat2.jpg" class="dish-photo" alt="Croquettes">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="dish-details-section">
|
||||||
|
<p class="dish-label">推荐菜品 #2 | ¥65</p>
|
||||||
|
<p class="dish-title">意式炸肉丸<br>Croquettes</p>
|
||||||
|
|
||||||
|
<div class="keyword-item">
|
||||||
|
<p class="keyword-txt">✨ 金黄酥脆 外壳完美</p>
|
||||||
|
</div>
|
||||||
|
<div class="keyword-item">
|
||||||
|
<p class="keyword-txt">🥩 肉质鲜嫩 多汁饱满</p>
|
||||||
|
</div>
|
||||||
|
<div class="keyword-item">
|
||||||
|
<p class="keyword-txt">🧈 奶油酱汁 香草点缀</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flag-badge badge-white"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 5: Price & Evaluation -->
|
||||||
|
<div class="slide slide-5">
|
||||||
|
<div class="eval-head"></div>
|
||||||
|
<p class="eval-head-txt">综合评价 | VALUTAZIONE</p>
|
||||||
|
|
||||||
|
<div class="eval-item-1">
|
||||||
|
<p class="eval-label">💵 价格区间</p>
|
||||||
|
<p class="eval-value">¥65-75/道菜</p>
|
||||||
|
<p class="eval-detail">人均约¥136</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="eval-item-2">
|
||||||
|
<p class="eval-label">⭐ 性价比</p>
|
||||||
|
<p class="eval-value">优秀</p>
|
||||||
|
<p class="eval-detail">物超所值</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="eval-item-3">
|
||||||
|
<p class="eval-label">👨🍳 服务</p>
|
||||||
|
<p class="eval-value">热情周到</p>
|
||||||
|
<p class="eval-detail">专业细致</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="eval-item-4">
|
||||||
|
<p class="eval-label">🏆 总体评分</p>
|
||||||
|
<p class="eval-value">4.4/5 ★★★★</p>
|
||||||
|
<p class="eval-detail">强烈推荐</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="final-box">
|
||||||
|
<p class="final-msg">正宗意式风味 · 温馨舒适环境 · 值得一试!</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flag-badge badge-red"></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
24
work_chinese/PPT04122025/_build/generate_pptx.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
const pptxgen = require('pptxgenjs');
|
||||||
|
const html2pptx = require('/mnt/e/Users/Alexis Trouvé/Documents/Projets/couple_matters/.claude/skills/pptx/scripts/html2pptx.js');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
async function generatePresentation() {
|
||||||
|
const pptx = new pptxgen();
|
||||||
|
pptx.layout = 'LAYOUT_16x9';
|
||||||
|
|
||||||
|
const htmlFile = path.join(__dirname, 'alimentari_piccolo.html');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await html2pptx(htmlFile, pptx);
|
||||||
|
|
||||||
|
const outputPath = path.join(__dirname, '..', 'Alimentari_Piccolo.pptx');
|
||||||
|
await pptx.writeFile({ fileName: outputPath });
|
||||||
|
|
||||||
|
console.log(`✅ Présentation créée avec succès: ${outputPath}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Erreur lors de la génération:', error.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generatePresentation();
|
||||||
BIN
work_chinese/PPT04122025/_build/outside.jpg
Normal file
|
After Width: | Height: | Size: 366 KiB |
BIN
work_chinese/PPT04122025/_build/plat1.jpg
Normal file
|
After Width: | Height: | Size: 338 KiB |
BIN
work_chinese/PPT04122025/_build/plat2.jpg
Normal file
|
After Width: | Height: | Size: 113 KiB |
106
work_chinese/PPT04122025/create_alimentari.js
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
const pptxgen = require('pptxgenjs');
|
||||||
|
const path = require('path');
|
||||||
|
const html2pptx = require('../../.claude/skills/pptx/scripts/html2pptx.js');
|
||||||
|
|
||||||
|
async function createPresentation() {
|
||||||
|
console.log('🍝 Création présentation Alimentari Piccolo (Design LUXE)...\n');
|
||||||
|
|
||||||
|
const pptx = new pptxgen();
|
||||||
|
pptx.layout = 'LAYOUT_16x9';
|
||||||
|
pptx.author = 'Alexis - Xiezuo Course';
|
||||||
|
pptx.title = 'Alimentari Piccolo - 意大利餐吧评价';
|
||||||
|
pptx.subject = '餐厅评价作业';
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Slide 1: Title
|
||||||
|
console.log('📄 Slide 1: 封面 LUXE...');
|
||||||
|
await html2pptx(
|
||||||
|
path.join(__dirname, 'slides/slide1_title.html'),
|
||||||
|
pptx,
|
||||||
|
{ tmpDir: '/tmp' }
|
||||||
|
);
|
||||||
|
|
||||||
|
// Slide 2: Location
|
||||||
|
console.log('📄 Slide 2: 位置 (hero photo + overlay)...');
|
||||||
|
await html2pptx(
|
||||||
|
path.join(__dirname, 'slides/slide2_location.html'),
|
||||||
|
pptx,
|
||||||
|
{ tmpDir: '/tmp' }
|
||||||
|
);
|
||||||
|
|
||||||
|
// Slide 3: Piadina
|
||||||
|
console.log('📄 Slide 3: Piadina (asymétrique)...');
|
||||||
|
await html2pptx(
|
||||||
|
path.join(__dirname, 'slides/slide3_piadina.html'),
|
||||||
|
pptx,
|
||||||
|
{ tmpDir: '/tmp' }
|
||||||
|
);
|
||||||
|
|
||||||
|
// Slide 4: Croquettes
|
||||||
|
console.log('📄 Slide 4: Croquettes (asymétrique inversé)...');
|
||||||
|
await html2pptx(
|
||||||
|
path.join(__dirname, 'slides/slide4_croquettes.html'),
|
||||||
|
pptx,
|
||||||
|
{ tmpDir: '/tmp' }
|
||||||
|
);
|
||||||
|
|
||||||
|
// Slide 5: Ambiance
|
||||||
|
console.log('📄 Slide 5: Ambiance intérieure + évaluation...');
|
||||||
|
await html2pptx(
|
||||||
|
path.join(__dirname, 'slides/slide5_ambiance.html'),
|
||||||
|
pptx,
|
||||||
|
{ tmpDir: '/tmp' }
|
||||||
|
);
|
||||||
|
|
||||||
|
// Slide 6: Menu
|
||||||
|
console.log('📄 Slide 6: Menu (carte CN uniquement)...');
|
||||||
|
await html2pptx(
|
||||||
|
path.join(__dirname, 'slides/slide6_menu.html'),
|
||||||
|
pptx,
|
||||||
|
{ tmpDir: '/tmp' }
|
||||||
|
);
|
||||||
|
|
||||||
|
// Slide 7: Credits
|
||||||
|
console.log('📄 Slide 7: Crédits (noms membres)...');
|
||||||
|
await html2pptx(
|
||||||
|
path.join(__dirname, 'slides/slide7_credits.html'),
|
||||||
|
pptx,
|
||||||
|
{ tmpDir: '/tmp' }
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save
|
||||||
|
const outputFile = 'Alimentari_Piccolo_v3.pptx';
|
||||||
|
await pptx.writeFile({ fileName: path.join(__dirname, outputFile) });
|
||||||
|
|
||||||
|
console.log('\n✅ 演示文稿创建成功!');
|
||||||
|
console.log(`📁 文件名: ${outputFile}`);
|
||||||
|
console.log('📍 位置: work_chinese/PPT04122025/');
|
||||||
|
console.log('\n🎨 Design LUXE & CLASSE :');
|
||||||
|
console.log(' ✓ Fond noir #1A1A1A (ultra-premium)');
|
||||||
|
console.log(' ✓ Or riche #D4AF37 (signature)');
|
||||||
|
console.log(' ✓ Vert forêt #2D5016 + Bordeaux #8B1A1A');
|
||||||
|
console.log(' ✓ Barre dorée verticale SIGNATURE');
|
||||||
|
console.log(' ✓ Pattern géométrique italien');
|
||||||
|
console.log(' ✓ Drapeau diagonal 3 bandes (rotation globale)');
|
||||||
|
console.log(' ✓ TOUTES les images utilisées');
|
||||||
|
console.log(' ✓ Design asymétrique luxueux');
|
||||||
|
console.log(' ✓ Texte 100% chinois/italien (zéro anglais)');
|
||||||
|
console.log(' ✓ 7 slides premium');
|
||||||
|
console.log('\n📝 Contenu :');
|
||||||
|
console.log(' 1. Titre LUXE avec pattern géométrique');
|
||||||
|
console.log(' 2. Hero photo extérieur + overlay info (位置/评分/价格)');
|
||||||
|
console.log(' 3. Piadina (grande photo gauche, info droite)');
|
||||||
|
console.log(' 4. Croquettes (inversé : info gauche, photo droite)');
|
||||||
|
console.log(' 5. Ambiance intérieure (2 photos) + évaluation');
|
||||||
|
console.log(' 6. Menu (carte CN uniquement, centrée)');
|
||||||
|
console.log(' 7. Crédits (李知珉、闵智铉、亓昊天)');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('\n❌ 错误:', error.message);
|
||||||
|
if (error.stack) {
|
||||||
|
console.error('\nStack:', error.stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createPresentation();
|
||||||
148
work_chinese/PPT04122025/slides/slide1_title.html
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
html { background: #ffffff; }
|
||||||
|
body {
|
||||||
|
width: 720pt;
|
||||||
|
height: 405pt;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: #1A1A1A;
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-content {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Italian flag diagonal */
|
||||||
|
.flag-diagonal {
|
||||||
|
position: absolute;
|
||||||
|
top: -20pt;
|
||||||
|
left: -20pt;
|
||||||
|
width: 120pt;
|
||||||
|
height: 120pt;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0.8;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-green {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #2D5016;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-white {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 33.33%;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #F5F5DC;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-red {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #8B1A1A;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Signature gold bar */
|
||||||
|
.gold-bar {
|
||||||
|
position: absolute;
|
||||||
|
right: 60pt;
|
||||||
|
top: 60pt;
|
||||||
|
bottom: 60pt;
|
||||||
|
width: 3pt;
|
||||||
|
background: #D4AF37;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main title */
|
||||||
|
.title-container {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 80pt;
|
||||||
|
right: 100pt;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-container h1 {
|
||||||
|
font-size: 56pt;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #D4AF37;
|
||||||
|
margin: 0 0 20pt 0;
|
||||||
|
padding: 0;
|
||||||
|
letter-spacing: 3pt;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-container p {
|
||||||
|
font-size: 20pt;
|
||||||
|
color: #C9C9C9;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-weight: 300;
|
||||||
|
letter-spacing: 1pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Geometric pattern */
|
||||||
|
.pattern {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 40pt;
|
||||||
|
left: 80pt;
|
||||||
|
width: 60pt;
|
||||||
|
height: 60pt;
|
||||||
|
border: 2pt solid #D4AF37;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pattern-inner {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 30pt;
|
||||||
|
height: 30pt;
|
||||||
|
border: 2pt solid #D4AF37;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="slide-content">
|
||||||
|
<div class="flag-diagonal">
|
||||||
|
<div class="flag-green"></div>
|
||||||
|
<div class="flag-white"></div>
|
||||||
|
<div class="flag-red"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gold-bar"></div>
|
||||||
|
|
||||||
|
<div class="title-container">
|
||||||
|
<h1>ALIMENTARI<br>PICCOLO</h1>
|
||||||
|
<p>意大利餐吧 · 番禺路</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pattern">
|
||||||
|
<div class="pattern-inner"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
155
work_chinese/PPT04122025/slides/slide2_ambiance.html
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
html { background: #ffffff; }
|
||||||
|
body {
|
||||||
|
width: 720pt;
|
||||||
|
height: 405pt;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: #F5EFE0;
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-content {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Italian flag diagonal */
|
||||||
|
.flag-diagonal {
|
||||||
|
position: absolute;
|
||||||
|
top: -20pt;
|
||||||
|
left: -20pt;
|
||||||
|
width: 120pt;
|
||||||
|
height: 120pt;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-green {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #8B9B83;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-white {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 33.33%;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-red {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #B8867D;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Photo grid */
|
||||||
|
.photo-grid {
|
||||||
|
position: absolute;
|
||||||
|
top: 40pt;
|
||||||
|
left: 40pt;
|
||||||
|
right: 40pt;
|
||||||
|
bottom: 140pt;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 15pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-large {
|
||||||
|
grid-column: span 2;
|
||||||
|
border-radius: 8pt;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 4pt 20pt rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-small {
|
||||||
|
border-radius: 8pt;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 4pt 20pt rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-large img,
|
||||||
|
.photo-small img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Info bar */
|
||||||
|
.info-bar {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 50pt;
|
||||||
|
left: 40pt;
|
||||||
|
right: 40pt;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item p {
|
||||||
|
font-size: 16pt;
|
||||||
|
color: #8B9B83;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-value {
|
||||||
|
font-size: 20pt;
|
||||||
|
color: #B8867D;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-top: 5pt;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="slide-content">
|
||||||
|
<div class="flag-diagonal">
|
||||||
|
<div class="flag-green"></div>
|
||||||
|
<div class="flag-white"></div>
|
||||||
|
<div class="flag-red"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="photo-grid">
|
||||||
|
<div class="photo-large">
|
||||||
|
<img src="file:///tmp/pptx_build/OutsideResto.jpg" alt="Outside">
|
||||||
|
</div>
|
||||||
|
<div class="photo-small">
|
||||||
|
<img src="file:///tmp/pptx_build/InsideResto.jpg" alt="Inside">
|
||||||
|
</div>
|
||||||
|
<div class="photo-small">
|
||||||
|
<img src="file:///tmp/pptx_build/LayoutTable.jpg" alt="Table">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-bar">
|
||||||
|
<div class="info-item">
|
||||||
|
<p>📍</p>
|
||||||
|
<p class="info-value">番禺路390号</p>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<p>⭐</p>
|
||||||
|
<p class="info-value">4.4/5</p>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<p>💰</p>
|
||||||
|
<p class="info-value">¥136/人</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
162
work_chinese/PPT04122025/slides/slide2_location.html
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
html { background: #ffffff; }
|
||||||
|
body {
|
||||||
|
width: 720pt;
|
||||||
|
height: 405pt;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: #1A1A1A;
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-content {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Italian flag diagonal */
|
||||||
|
.flag-diagonal {
|
||||||
|
position: absolute;
|
||||||
|
top: -20pt;
|
||||||
|
left: -20pt;
|
||||||
|
width: 120pt;
|
||||||
|
height: 120pt;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0.8;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-green {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #2D5016;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-white {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 33.33%;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #F5F5DC;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-red {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #8B1A1A;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Signature gold bar */
|
||||||
|
.gold-bar {
|
||||||
|
position: absolute;
|
||||||
|
right: 60pt;
|
||||||
|
top: 60pt;
|
||||||
|
bottom: 60pt;
|
||||||
|
width: 3pt;
|
||||||
|
background: #D4AF37;
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main photo */
|
||||||
|
.hero-photo {
|
||||||
|
position: absolute;
|
||||||
|
top: 60pt;
|
||||||
|
left: 60pt;
|
||||||
|
right: 100pt;
|
||||||
|
bottom: 160pt;
|
||||||
|
border-radius: 4pt;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 8pt 30pt rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-photo img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Info overlay */
|
||||||
|
.info-overlay {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 60pt;
|
||||||
|
left: 60pt;
|
||||||
|
right: 100pt;
|
||||||
|
height: 80pt;
|
||||||
|
background: rgba(26, 26, 26, 0.95);
|
||||||
|
border-left: 4pt solid #D4AF37;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
padding: 0 30pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item p:first-child {
|
||||||
|
font-size: 14pt;
|
||||||
|
color: #999999;
|
||||||
|
margin: 0 0 5pt 0;
|
||||||
|
padding: 0;
|
||||||
|
letter-spacing: 1pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item p:last-child {
|
||||||
|
font-size: 22pt;
|
||||||
|
color: #D4AF37;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="slide-content">
|
||||||
|
<div class="flag-diagonal">
|
||||||
|
<div class="flag-green"></div>
|
||||||
|
<div class="flag-white"></div>
|
||||||
|
<div class="flag-red"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gold-bar"></div>
|
||||||
|
|
||||||
|
<div class="hero-photo">
|
||||||
|
<img src="file:///tmp/pptx_build/OutsideResto.jpg" alt="Outside">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-overlay">
|
||||||
|
<div class="info-item">
|
||||||
|
<p>位置</p>
|
||||||
|
<p>番禺路390号</p>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<p>评分</p>
|
||||||
|
<p>4.4★</p>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<p>价格</p>
|
||||||
|
<p>¥136</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
179
work_chinese/PPT04122025/slides/slide3_piadina.html
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
html { background: #ffffff; }
|
||||||
|
body {
|
||||||
|
width: 720pt;
|
||||||
|
height: 405pt;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: #1A1A1A;
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-content {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Italian flag diagonal */
|
||||||
|
.flag-diagonal {
|
||||||
|
position: absolute;
|
||||||
|
top: -20pt;
|
||||||
|
left: -20pt;
|
||||||
|
width: 120pt;
|
||||||
|
height: 120pt;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0.8;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-green {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #2D5016;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-white {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 33.33%;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #F5F5DC;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-red {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #8B1A1A;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Signature gold bar */
|
||||||
|
.gold-bar {
|
||||||
|
position: absolute;
|
||||||
|
right: 300pt;
|
||||||
|
top: 60pt;
|
||||||
|
bottom: 60pt;
|
||||||
|
width: 3pt;
|
||||||
|
background: #D4AF37;
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dish photo */
|
||||||
|
.dish-photo {
|
||||||
|
position: absolute;
|
||||||
|
top: 60pt;
|
||||||
|
left: 60pt;
|
||||||
|
right: 330pt;
|
||||||
|
bottom: 80pt;
|
||||||
|
border-radius: 4pt;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 8pt 30pt rgba(0, 0, 0, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dish-photo img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Info section */
|
||||||
|
.dish-info {
|
||||||
|
position: absolute;
|
||||||
|
right: 60pt;
|
||||||
|
top: 120pt;
|
||||||
|
width: 200pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dish-info h1 {
|
||||||
|
font-size: 38pt;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #D4AF37;
|
||||||
|
margin: 0 0 10pt 0;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 1.1;
|
||||||
|
letter-spacing: 1pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dish-info p {
|
||||||
|
font-size: 16pt;
|
||||||
|
color: #8B8B8B;
|
||||||
|
margin: 0 0 30pt 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keyword-box {
|
||||||
|
margin: 10pt 0;
|
||||||
|
padding: 0 0 0 15pt;
|
||||||
|
border-left: 2pt solid #2D5016;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keyword-box p {
|
||||||
|
font-size: 14pt;
|
||||||
|
color: #C9C9C9;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Price */
|
||||||
|
.price {
|
||||||
|
position: absolute;
|
||||||
|
right: 60pt;
|
||||||
|
bottom: 60pt;
|
||||||
|
font-size: 32pt;
|
||||||
|
color: #D4AF37;
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
letter-spacing: 2pt;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="slide-content">
|
||||||
|
<div class="flag-diagonal">
|
||||||
|
<div class="flag-green"></div>
|
||||||
|
<div class="flag-white"></div>
|
||||||
|
<div class="flag-red"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gold-bar"></div>
|
||||||
|
|
||||||
|
<div class="dish-photo">
|
||||||
|
<img src="file:///tmp/pptx_build/piadina.jpg" alt="Piadina">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="dish-info">
|
||||||
|
<h1>PIADINA</h1>
|
||||||
|
<p>意式皮亚迪纳</p>
|
||||||
|
<div class="keyword-box">
|
||||||
|
<p>现烤薄饼</p>
|
||||||
|
</div>
|
||||||
|
<div class="keyword-box">
|
||||||
|
<p>新鲜蔬菜</p>
|
||||||
|
</div>
|
||||||
|
<div class="keyword-box">
|
||||||
|
<p>意式火腿</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="price">¥65-75</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
179
work_chinese/PPT04122025/slides/slide4_croquettes.html
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
html { background: #ffffff; }
|
||||||
|
body {
|
||||||
|
width: 720pt;
|
||||||
|
height: 405pt;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: #1A1A1A;
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-content {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Italian flag diagonal */
|
||||||
|
.flag-diagonal {
|
||||||
|
position: absolute;
|
||||||
|
top: -20pt;
|
||||||
|
left: -20pt;
|
||||||
|
width: 120pt;
|
||||||
|
height: 120pt;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0.8;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-green {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #2D5016;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-white {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 33.33%;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #F5F5DC;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-red {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #8B1A1A;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Signature gold bar */
|
||||||
|
.gold-bar {
|
||||||
|
position: absolute;
|
||||||
|
left: 300pt;
|
||||||
|
top: 60pt;
|
||||||
|
bottom: 60pt;
|
||||||
|
width: 3pt;
|
||||||
|
background: #D4AF37;
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dish photo */
|
||||||
|
.dish-photo {
|
||||||
|
position: absolute;
|
||||||
|
top: 60pt;
|
||||||
|
right: 60pt;
|
||||||
|
left: 330pt;
|
||||||
|
bottom: 80pt;
|
||||||
|
border-radius: 4pt;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 8pt 30pt rgba(0, 0, 0, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dish-photo img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Info section */
|
||||||
|
.dish-info {
|
||||||
|
position: absolute;
|
||||||
|
left: 60pt;
|
||||||
|
top: 120pt;
|
||||||
|
width: 200pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dish-info h1 {
|
||||||
|
font-size: 36pt;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #D4AF37;
|
||||||
|
margin: 0 0 10pt 0;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 1.1;
|
||||||
|
letter-spacing: 1pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dish-info p {
|
||||||
|
font-size: 16pt;
|
||||||
|
color: #8B8B8B;
|
||||||
|
margin: 0 0 30pt 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keyword-box {
|
||||||
|
margin: 10pt 0;
|
||||||
|
padding: 0 0 0 15pt;
|
||||||
|
border-left: 2pt solid #8B1A1A;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keyword-box p {
|
||||||
|
font-size: 14pt;
|
||||||
|
color: #C9C9C9;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Price */
|
||||||
|
.price {
|
||||||
|
position: absolute;
|
||||||
|
left: 60pt;
|
||||||
|
bottom: 60pt;
|
||||||
|
font-size: 32pt;
|
||||||
|
color: #D4AF37;
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
letter-spacing: 2pt;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="slide-content">
|
||||||
|
<div class="flag-diagonal">
|
||||||
|
<div class="flag-green"></div>
|
||||||
|
<div class="flag-white"></div>
|
||||||
|
<div class="flag-red"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gold-bar"></div>
|
||||||
|
|
||||||
|
<div class="dish-photo">
|
||||||
|
<img src="file:///tmp/pptx_build/croquettes.jpg" alt="Croquettes">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="dish-info">
|
||||||
|
<h1>CROQUETTES</h1>
|
||||||
|
<p>意式炸肉丸</p>
|
||||||
|
<div class="keyword-box">
|
||||||
|
<p>金黄酥脆</p>
|
||||||
|
</div>
|
||||||
|
<div class="keyword-box">
|
||||||
|
<p>肉质鲜嫩</p>
|
||||||
|
</div>
|
||||||
|
<div class="keyword-box">
|
||||||
|
<p>奶油酱汁</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="price">¥65</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
180
work_chinese/PPT04122025/slides/slide5_ambiance.html
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
html { background: #ffffff; }
|
||||||
|
body {
|
||||||
|
width: 720pt;
|
||||||
|
height: 405pt;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: #1A1A1A;
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-content {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Italian flag diagonal */
|
||||||
|
.flag-diagonal {
|
||||||
|
position: absolute;
|
||||||
|
top: -20pt;
|
||||||
|
left: -20pt;
|
||||||
|
width: 120pt;
|
||||||
|
height: 120pt;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0.8;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-green {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #2D5016;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-white {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 33.33%;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #F5F5DC;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-red {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #8B1A1A;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Signature gold bar */
|
||||||
|
.gold-bar {
|
||||||
|
position: absolute;
|
||||||
|
right: 60pt;
|
||||||
|
top: 60pt;
|
||||||
|
bottom: 60pt;
|
||||||
|
width: 3pt;
|
||||||
|
background: #D4AF37;
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Photos section */
|
||||||
|
.photo-left {
|
||||||
|
position: absolute;
|
||||||
|
top: 60pt;
|
||||||
|
left: 60pt;
|
||||||
|
width: 270pt;
|
||||||
|
bottom: 80pt;
|
||||||
|
border-radius: 4pt;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 6pt 25pt rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-left img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-right {
|
||||||
|
position: absolute;
|
||||||
|
top: 60pt;
|
||||||
|
left: 350pt;
|
||||||
|
right: 100pt;
|
||||||
|
bottom: 190pt;
|
||||||
|
border-radius: 4pt;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 6pt 25pt rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-right img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Evaluation section */
|
||||||
|
.eval-panel {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 60pt;
|
||||||
|
left: 350pt;
|
||||||
|
right: 100pt;
|
||||||
|
height: 100pt;
|
||||||
|
background: rgba(26, 26, 26, 0.95);
|
||||||
|
border-left: 4pt solid #D4AF37;
|
||||||
|
padding: 20pt 25pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eval-panel h2 {
|
||||||
|
font-size: 20pt;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #D4AF37;
|
||||||
|
margin: 0 0 15pt 0;
|
||||||
|
padding: 0;
|
||||||
|
letter-spacing: 2pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eval-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eval-row p {
|
||||||
|
font-size: 14pt;
|
||||||
|
color: #999999;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eval-row p span {
|
||||||
|
color: #C9C9C9;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="slide-content">
|
||||||
|
<div class="flag-diagonal">
|
||||||
|
<div class="flag-green"></div>
|
||||||
|
<div class="flag-white"></div>
|
||||||
|
<div class="flag-red"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gold-bar"></div>
|
||||||
|
|
||||||
|
<div class="photo-left">
|
||||||
|
<img src="file:///tmp/pptx_build/InsideResto.jpg" alt="Inside">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="photo-right">
|
||||||
|
<img src="file:///tmp/pptx_build/LayoutTable.jpg" alt="Table">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="eval-panel">
|
||||||
|
<h2>VALUTAZIONE</h2>
|
||||||
|
<div class="eval-row">
|
||||||
|
<p>性价比 <span>优秀</span></p>
|
||||||
|
<p>服务 <span>热情</span></p>
|
||||||
|
<p>环境 <span>舒适</span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
168
work_chinese/PPT04122025/slides/slide5_conclusion.html
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
html { background: #ffffff; }
|
||||||
|
body {
|
||||||
|
width: 720pt;
|
||||||
|
height: 405pt;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: #F5EFE0;
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-content {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Italian flag diagonal */
|
||||||
|
.flag-diagonal {
|
||||||
|
position: absolute;
|
||||||
|
top: -20pt;
|
||||||
|
left: -20pt;
|
||||||
|
width: 120pt;
|
||||||
|
height: 120pt;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-green {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #8B9B83;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-white {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 33.33%;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-red {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #B8867D;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Menu photos */
|
||||||
|
.menu-photos {
|
||||||
|
position: absolute;
|
||||||
|
top: 40pt;
|
||||||
|
left: 40pt;
|
||||||
|
right: 40pt;
|
||||||
|
height: 180pt;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 20pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-card {
|
||||||
|
border-radius: 10pt;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 4pt 15pt rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-card img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Evaluation section */
|
||||||
|
.eval-section {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 50pt;
|
||||||
|
left: 40pt;
|
||||||
|
right: 40pt;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eval-section h2 {
|
||||||
|
font-size: 28pt;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #8B9B83;
|
||||||
|
margin: 0 0 15pt 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eval-grid {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
margin-top: 15pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eval-item p {
|
||||||
|
font-size: 15pt;
|
||||||
|
color: #666666;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eval-value {
|
||||||
|
font-size: 20pt;
|
||||||
|
color: #B8867D;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-top: 5pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
width: 60pt;
|
||||||
|
height: 1pt;
|
||||||
|
background: #C9A976;
|
||||||
|
margin: 15pt auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="slide-content">
|
||||||
|
<div class="flag-diagonal">
|
||||||
|
<div class="flag-green"></div>
|
||||||
|
<div class="flag-white"></div>
|
||||||
|
<div class="flag-red"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="menu-photos">
|
||||||
|
<div class="menu-card">
|
||||||
|
<img src="file:///tmp/pptx_build/CarteCNNice.jpg" alt="Menu">
|
||||||
|
</div>
|
||||||
|
<div class="menu-card">
|
||||||
|
<img src="file:///tmp/pptx_build/CarteENTravers.jpg" alt="Menu">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="eval-section">
|
||||||
|
<div class="divider"></div>
|
||||||
|
<h2>值得一试</h2>
|
||||||
|
|
||||||
|
<div class="eval-grid">
|
||||||
|
<div class="eval-item">
|
||||||
|
<p>性价比</p>
|
||||||
|
<p class="eval-value">优秀</p>
|
||||||
|
</div>
|
||||||
|
<div class="eval-item">
|
||||||
|
<p>服务</p>
|
||||||
|
<p class="eval-value">热情</p>
|
||||||
|
</div>
|
||||||
|
<div class="eval-item">
|
||||||
|
<p>环境</p>
|
||||||
|
<p class="eval-value">舒适</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
150
work_chinese/PPT04122025/slides/slide6_menu.html
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
html { background: #ffffff; }
|
||||||
|
body {
|
||||||
|
width: 720pt;
|
||||||
|
height: 405pt;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: #1A1A1A;
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-content {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Italian flag diagonal */
|
||||||
|
.flag-diagonal {
|
||||||
|
position: absolute;
|
||||||
|
top: -20pt;
|
||||||
|
left: -20pt;
|
||||||
|
width: 120pt;
|
||||||
|
height: 120pt;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0.8;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-green {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #2D5016;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-white {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 33.33%;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #F5F5DC;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-red {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #8B1A1A;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Signature gold bar */
|
||||||
|
.gold-bar {
|
||||||
|
position: absolute;
|
||||||
|
right: 60pt;
|
||||||
|
top: 60pt;
|
||||||
|
bottom: 60pt;
|
||||||
|
width: 3pt;
|
||||||
|
background: #D4AF37;
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Menu photo centered */
|
||||||
|
.menu-center {
|
||||||
|
position: absolute;
|
||||||
|
top: 80pt;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: 300pt;
|
||||||
|
height: 260pt;
|
||||||
|
border-radius: 4pt;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 8pt 30pt rgba(0, 0, 0, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-center img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Title */
|
||||||
|
.menu-title {
|
||||||
|
position: absolute;
|
||||||
|
top: 80pt;
|
||||||
|
left: 60pt;
|
||||||
|
right: 100pt;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-title h1 {
|
||||||
|
font-size: 32pt;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #D4AF37;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
letter-spacing: 3pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Geometric pattern */
|
||||||
|
.pattern {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 60pt;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: 50pt;
|
||||||
|
height: 50pt;
|
||||||
|
border: 2pt solid #D4AF37;
|
||||||
|
transform: translateX(-50%) rotate(45deg);
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="slide-content">
|
||||||
|
<div class="flag-diagonal">
|
||||||
|
<div class="flag-green"></div>
|
||||||
|
<div class="flag-white"></div>
|
||||||
|
<div class="flag-red"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gold-bar"></div>
|
||||||
|
|
||||||
|
<div class="menu-title">
|
||||||
|
<h1>菜单</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="menu-center">
|
||||||
|
<img src="file:///tmp/pptx_build/CarteCNNice.jpg" alt="Menu CN">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pattern"></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
148
work_chinese/PPT04122025/slides/slide7_credits.html
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
html { background: #ffffff; }
|
||||||
|
body {
|
||||||
|
width: 720pt;
|
||||||
|
height: 405pt;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: #1A1A1A;
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-content {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Italian flag diagonal */
|
||||||
|
.flag-diagonal {
|
||||||
|
position: absolute;
|
||||||
|
top: -20pt;
|
||||||
|
left: -20pt;
|
||||||
|
width: 120pt;
|
||||||
|
height: 120pt;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0.8;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-green {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #2D5016;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-white {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 33.33%;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #F5F5DC;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-red {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 33.33%;
|
||||||
|
height: 100%;
|
||||||
|
background: #8B1A1A;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: top right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Signature gold bar */
|
||||||
|
.gold-bar {
|
||||||
|
position: absolute;
|
||||||
|
right: 60pt;
|
||||||
|
top: 60pt;
|
||||||
|
bottom: 60pt;
|
||||||
|
width: 3pt;
|
||||||
|
background: #D4AF37;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Credits container */
|
||||||
|
.credits {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 80pt;
|
||||||
|
right: 100pt;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credits h1 {
|
||||||
|
font-size: 40pt;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #D4AF37;
|
||||||
|
margin: 0 0 50pt 0;
|
||||||
|
padding: 0;
|
||||||
|
letter-spacing: 3pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.names {
|
||||||
|
font-size: 28pt;
|
||||||
|
color: #C9C9C9;
|
||||||
|
line-height: 1.8;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
letter-spacing: 2pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Geometric pattern */
|
||||||
|
.pattern {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 40pt;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%) rotate(45deg);
|
||||||
|
width: 60pt;
|
||||||
|
height: 60pt;
|
||||||
|
border: 2pt solid #D4AF37;
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pattern-inner {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 30pt;
|
||||||
|
height: 30pt;
|
||||||
|
border: 2pt solid #D4AF37;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="slide-content">
|
||||||
|
<div class="flag-diagonal">
|
||||||
|
<div class="flag-green"></div>
|
||||||
|
<div class="flag-white"></div>
|
||||||
|
<div class="flag-red"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gold-bar"></div>
|
||||||
|
|
||||||
|
<div class="credits">
|
||||||
|
<h1>GRAZIE</h1>
|
||||||
|
<p class="names">李知珉<br>闵智铉<br>亓昊天</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pattern">
|
||||||
|
<div class="pattern-inner"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||