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
|
||||
→ 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
|
||||
→ Détails : `personnalités/Tingting.md`
|
||||
@ -73,7 +75,10 @@ Appliquer systématiquement pour tout problème :
|
||||
|
||||
### 💬 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
|
||||
- `README.md` : Explications du système
|
||||
- `_template.md` : Template pour nouveaux sujets
|
||||
@ -83,10 +88,13 @@ Appliquer systématiquement pour tout problème :
|
||||
|
||||
### 🔧 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`
|
||||
- **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
|
||||
- `.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
|
||||
**Plateforme** : PC (Steam)
|
||||
@ -960,7 +960,7 @@ La vue slice manquait de justification mécanique (bonus/malus arbitraires).
|
||||
|
||||
## 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ù** :
|
||||
- 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
|
||||
**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.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.4 : Renommage POKROVSK: IRON LINE → MOBILE COMMAND
|
||||
|
||||
---
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
# OCR PDF Service - Service OCR en Ligne
|
||||
|
||||
**Status**: CONCEPT
|
||||
**Created**: 19/11/2025
|
||||
**Status**: Conception
|
||||
**Moved to CONCEPT**: 30/11/2025 (depuis PAUSE)
|
||||
**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
|
||||
|
||||
**Statut** : 🔥 URGENT - En conception
|
||||
**Status** : PAUSE
|
||||
**Créé** : 17 novembre 2025
|
||||
**Moved to PAUSE** : 30 novembre 2025
|
||||
**Type** : Projet support multivecteur
|
||||
**Tentative** : Échec initial, relance prévue (besoin réel identifié)
|
||||
|
||||
---
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# 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
|
||||
**Fiche** : `WIP/GroveEngine.md`
|
||||
**Description** : Runtime engine conçu pour développement par IA
|
||||
**Stack** : À définir
|
||||
**Status** : Développement actif
|
||||
**Fiche** : `WIP/groveengine.md` (référence vers `C:\Users\alexi\Documents\projects\groveengine`)
|
||||
**Description** : Game Engine C++ modulaire avec hot-reload (0.4ms)
|
||||
**Stack** : C++17, bgfx, SDL2, nlohmann_json, spdlog
|
||||
**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`
|
||||
**Description** : Génération d'articles SEO avec anti-détection IA
|
||||
**Stack** : Node.js
|
||||
**Status** : En repurpose pour gérer du Fiverr
|
||||
**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
|
||||
**Fiche** : `PAUSE/Warfactory.md`
|
||||
**Description** : Jeu (engine en développement)
|
||||
**Description** : Simulation militaire industrielle (Factorio + stratégie)
|
||||
**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
|
||||
|
||||
### 2. chinese_audio_tts_pipeline
|
||||
**Fiche** : `PAUSE/chinese_audio_tts_pipeline.md`
|
||||
**Description** : Pipeline TTS pour génération audio chinois
|
||||
**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
|
||||
**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
|
||||
**Target** : Warfactory
|
||||
**Status** : Concept/Vision pas encore implémenté
|
||||
**Status** : Concept/Vision - Dépend de Warfactory (trop tôt)
|
||||
|
||||
### 4. ocr_pdf_service
|
||||
**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
|
||||
### 4. Essay_Writing_Tingting
|
||||
**Fiche** : `PAUSE/Essay_Writing_Tingting.md`
|
||||
**Description** : Accompagnement Tingting pour écriture essais
|
||||
**Status** : Promesse faite, détails à clarifier
|
||||
**Action requise** : Demander à Tingting cette semaine ou KILL
|
||||
**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`
|
||||
**Description** : JDR 4X construction de civilisation sur Discord
|
||||
**Players** : GM (Arthur Ignatus) + Joueur (Rubanc/Alexis)
|
||||
@ -88,15 +112,15 @@
|
||||
**Workflow** : Tours GM → Analyse → Réponse → Cycle
|
||||
**Status** : Actif, cycles continus
|
||||
|
||||
### 2. Database Cours Chinois
|
||||
### 3. Database Cours Chinois
|
||||
**Fiche** : `CONSTANT/Database_Cours_Chinois.md`
|
||||
**Description** : Base de données apprentissage chinois
|
||||
**Objectif** : Atteindre niveau Zhongyi (intermédiaire)
|
||||
**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)
|
||||
|
||||
### 3. Class Generator 2.0
|
||||
### 4. Class Generator 2.0
|
||||
**Fiche** : `CONSTANT/ClassGen_Analysis.md` + `Class_Generator_2.0.md`
|
||||
**Description** : Plateforme éducative interactive (anglais/chinois, enfants 8-9 ans)
|
||||
**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`
|
||||
**Description** : Survival horror réaliste (guerre moderne Ukraine)
|
||||
**Genre** : FPS/Survival horror, drones comme ennemi principal
|
||||
**Status** : Concept complet (41KB de design doc)
|
||||
**Note** : Version gestion à discuter
|
||||
|
||||
### 2. social_network_manager
|
||||
### 3. social_network_manager
|
||||
**Fiche** : `CONCEPT/social_network_manager.md`
|
||||
**Description** : Gestionnaire IA multi-plateformes sociales (6 plateformes)
|
||||
**Stack** : Browser-Use (Playwright + LLM vision)
|
||||
**Status** : Conception suspendue - Problèmes ToS/légaux
|
||||
**Créé** : 27 oct 2025
|
||||
|
||||
### 3. vps_tunnel_china
|
||||
### 4. vps_tunnel_china
|
||||
**Fiche** : `CONCEPT/vps_tunnel_china.md`
|
||||
**Description** : Setup VPN anti-GFW (contourner Great Firewall)
|
||||
**Stack** : V2Ray/WireGuard + obfuscation + Cloudflare
|
||||
**Contexte** : Shanghai
|
||||
**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`
|
||||
**Description** : Optimiser workflow multi-instances Claude
|
||||
**Idées** : Hooks, slash commands, coordination multi-instances
|
||||
**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
|
||||
|
||||
---
|
||||
|
||||
## ✅ 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
|
||||
|
||||
### Docs archivées
|
||||
- `MCP_Creative_Amplification.md` - Guide MCP (14 oct 2025, 927 lignes)
|
||||
- `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
|
||||
|
||||
**Total projets actifs** : 12 (4 WIP + 5 PAUSE + 3 CONSTANT)
|
||||
**Projets concepts** : 5
|
||||
**Archivés** : 2 docs
|
||||
**Total projets actifs** : 16 (5 WIP + 6 PAUSE + 4 CONSTANT)
|
||||
**Projets concepts** : 8 (dont AI_Team_System - meta-projet, Reddit_Save_Scraper)
|
||||
**Projets DONE** : 1 (videotoMP3Transcriptor) 🎉
|
||||
**Archivés** : 2 docs + 2 candidats
|
||||
|
||||
**Par domaine** :
|
||||
- Couple/Tingting : 1 (Essay Writing)
|
||||
- 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)
|
||||
- Créatif : 1 (civjdr)
|
||||
- Services : 2 (OCR PDF, VPS Tunnel)
|
||||
- Services : 3 (videotoMP3 DONE, OCR PDF, VPS Tunnel)
|
||||
- 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
|
||||
- ✅ Pas de perfectionnisme paralysant
|
||||
- ✅ Confiance dans les choix
|
||||
- **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)
|
||||
- ❌ Syndrome de l'imposteur
|
||||
- ❌ Syndrome de l'imposteur (diminué avec expérience)
|
||||
- ❌ Over-engineering compensatoire
|
||||
- ❌ Refactor en boucle
|
||||
- **Raison** : Se sent imposteur → Sur-compensation
|
||||
- **Contre-exemple** : videotoMP3 shipped en 2 jours (Node.js) → Pattern s'améliore
|
||||
|
||||
### Solution qui Marche
|
||||
**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
|
||||
- Difficulté à exécuter ce qui est "intellectuellement résolu"
|
||||
- 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
|
||||
- **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
|
||||
- **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
|
||||
- **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?"
|
||||
@ -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
|
||||
- **Pattern révélé** : Toujours lui qui initie conversations après conflits, épuisant
|
||||
- **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
|
||||
|
||||
|
||||
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
|
||||
|
||||
**Status** : 🔍 En réflexion
|
||||
**Status** : 🎯 En cours d'exécution
|
||||
**Date création** : 12 novembre 2025
|
||||
**Deadline** : 11 décembre 2025 (anniversaire)
|
||||
**Budget** : ~1000 yuan
|
||||
**Deadline** : 11 décembre 2025 (anniversaire) - **10 jours restants**
|
||||
**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
|
||||
- Montrer respect et considération
|
||||
- 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 :**
|
||||
- Anniversaire : 11 décembre
|
||||
- Âge : ~57 ans
|
||||
- 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
|
||||
- Culture / valeurs : Apprécie le prestige/statut social
|
||||
- ⚠️ É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) :**
|
||||
- Éviter cadeaux symboliquement négatifs (horloges, objets blancs/noirs selon contexte, chiffre 4)
|
||||
- Privilégier : Santé, longévité, prospérité, prestige
|
||||
- Qualité > Quantité (face importante)
|
||||
- Emballage soigné essentiel
|
||||
**Concept** :
|
||||
- Set mahjong niveau collection (pas pour jouer - il a déjà table auto)
|
||||
- Fonction : **Pièce d'art exposée** dans salon/bureau
|
||||
- Statement piece pour impressionner invités
|
||||
- Symbolique culture chinoise traditionnelle forte
|
||||
|
||||
**Pratiques :**
|
||||
- Utilisable / appréciable au quotidien vs décoratif
|
||||
- Âge du père (confort, santé, loisirs adaptés)
|
||||
- Shanghai / climat / mode de vie
|
||||
**Critères obligatoires** :
|
||||
- ✅ Matériaux premium : Bambou gravé, jade, bois précieux (红木), os
|
||||
- ✅ Coffret display vitré ou bois massif avec présentation soignée
|
||||
- ✅ 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 :**
|
||||
- Niveau de proximité actuel avec Alexis
|
||||
- Image à projeter (gendre sérieux, attentionné, respectueux)
|
||||
- Validation par Tingting essentielle
|
||||
**Pourquoi ce choix** :
|
||||
- ✅ Match "aquarium energy" (statement piece bold, mémorable, pas safe)
|
||||
- ✅ Compatible table auto (display séparé, pas de conflit)
|
||||
- ✅ 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 :**
|
||||
- [ ] Thé haut de gamme (collection qualité, coffret prestige)
|
||||
- [ ] Accessoires santé (masseur, coussin ergonomique)
|
||||
- [ ] Supplément traditionnel chinois haut de gamme (ginseng, etc.)
|
||||
**1er décembre (AUJOURD'HUI)** :
|
||||
- ✅ Décision prise : Set mahjong display
|
||||
- 🔄 Recherche Taobao avec termes chinois
|
||||
|
||||
**Catégorie Culture / Loisirs :**
|
||||
- [ ] Calligraphie (matériel qualité si pratique)
|
||||
- [ ] Livre collection / édition spéciale
|
||||
- [ ] Équipement hobby spécifique (à identifier)
|
||||
**2 décembre** :
|
||||
- Commander si bon listing trouvé (vérifier délai livraison Shanghai)
|
||||
- OU Achat physique Yu Garden/Dongtai Road si timing Taobao risqué
|
||||
|
||||
**Catégorie Prestige / Symbolique :**
|
||||
- [ ] Alcool prestigieux (baijiu qualité, cognac)
|
||||
- [ ] Objet décoratif traditionnel (jade, porcelaine)
|
||||
- [ ] Accessoire luxe quotidien (stylo, accessoire cuir)
|
||||
**3-8 décembre** :
|
||||
- Livraison/réception
|
||||
- Vérification qualité
|
||||
|
||||
**Catégorie Pratique / Confort :**
|
||||
- [ ] Vêtement qualité (matière premium)
|
||||
- [ ] Accessoire tech adapté seniors (si intérêt)
|
||||
- [ ] Objet confort maison
|
||||
**9 décembre** :
|
||||
- Emballage cadeau premium soigné
|
||||
- Préparation présentation
|
||||
|
||||
**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)
|
||||
- Deadline ?
|
||||
- Budget approprié selon contexte ?
|
||||
竹制麻将 收藏 礼盒
|
||||
(Mahjong bambou collection coffret cadeau)
|
||||
|
||||
2. **Profil du père**
|
||||
- Qu'est-ce qu'il aime faire au quotidien ?
|
||||
- Quels sont ses hobbies / passions ?
|
||||
- Qu'est-ce qu'il possède déjà qu'il apprécie beaucoup ?
|
||||
- Santé / limitations physiques à considérer ?
|
||||
玉石麻将 高档 展示盒
|
||||
(Mahjong jade haut de gamme boîte display)
|
||||
|
||||
3. **Préférences / Style**
|
||||
- Plutôt pratique ou symbolique ?
|
||||
- Plutôt traditionnel ou moderne ?
|
||||
- Qu'est-ce qui lui fait vraiment plaisir d'habitude ?
|
||||
红木麻将 礼品装
|
||||
(Mahjong bois précieux emballage cadeau)
|
||||
|
||||
4. **Contexte familial**
|
||||
- Qu'est-ce que d'autres membres de la famille ont offert qui a bien marché ?
|
||||
- Y a-t-il des attentes implicites ?
|
||||
- Comment il réagit aux cadeaux généralement ?
|
||||
手工雕刻麻将 收藏套装
|
||||
(Mahjong gravé main set collection)
|
||||
|
||||
5. **Validation**
|
||||
- Tingting a-t-elle des suggestions initiales ?
|
||||
- Qu'est-ce qui serait vraiment apprécié selon elle ?
|
||||
- Qu'est-ce qui serait maladroit ou à éviter absolument ?
|
||||
传统工艺麻将 高端礼盒
|
||||
(Mahjong artisanat traditionnel coffret haut gamme)
|
||||
```
|
||||
|
||||
**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
|
||||
|
||||
**Le cadeau idéal devra :**
|
||||
- ✅ Être culturellement approprié (pas de symbole négatif)
|
||||
- ✅ Correspondre au budget / contexte (ni trop ni pas assez)
|
||||
- ✅ Montrer considération / attention (pas générique)
|
||||
- ✅ Être validé par Tingting (elle connaît son père)
|
||||
- ✅ Qualité visible (emballage inclus)
|
||||
- ✅ Utilisable / appréciable réellement
|
||||
- ✅ Être culturellement approprié (mahjong = symbolique forte)
|
||||
- ✅ Correspondre au budget (700-800 yuan)
|
||||
- ✅ Montrer considération / attention (artisanal, pas générique)
|
||||
- ✅ Qualité visible (matériaux premium, coffret soigné)
|
||||
- ✅ Statement piece mémorable (match aquarium)
|
||||
- ✅ Non-consommable, durable
|
||||
- ✅ Livrable avant deadline
|
||||
|
||||
---
|
||||
|
||||
## Next steps
|
||||
|
||||
**☐ 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
|
||||
**Date dernière mise à jour** : 1er décembre 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>
|
||||