@linklabjs/core 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/dist/scenarios/test-metro-paris/config.json +0 -6
- package/dist/scenarios/test-metro-paris/graph.json +0 -16325
- package/dist/scenarios/test-metro-paris/queries.d.ts +0 -22
- package/dist/scenarios/test-metro-paris/queries.d.ts.map +0 -1
- package/dist/scenarios/test-metro-paris/queries.js +0 -128
- package/dist/scenarios/test-metro-paris/queries.js.map +0 -1
- package/dist/scenarios/test-metro-paris/stack.json +0 -1
- package/dist/scenarios/test-musicians/config.json +0 -10
- package/dist/scenarios/test-musicians/graph.json +0 -20
- package/dist/scenarios/test-musicians/stack.json +0 -1
- package/dist/scenarios/test-netflix/actions.d.ts +0 -14
- package/dist/scenarios/test-netflix/actions.d.ts.map +0 -1
- package/dist/scenarios/test-netflix/actions.js +0 -86
- package/dist/scenarios/test-netflix/actions.js.map +0 -1
- package/dist/scenarios/test-netflix/config.json +0 -6
- package/dist/scenarios/test-netflix/data/categories.json +0 -1
- package/dist/scenarios/test-netflix/data/companies.json +0 -1
- package/dist/scenarios/test-netflix/data/credits.json +0 -19797
- package/dist/scenarios/test-netflix/data/departments.json +0 -18
- package/dist/scenarios/test-netflix/data/jobs.json +0 -142
- package/dist/scenarios/test-netflix/data/movies.json +0 -3497
- package/dist/scenarios/test-netflix/data/people.json +0 -1
- package/dist/scenarios/test-netflix/data/synonyms.json +0 -7
- package/dist/scenarios/test-netflix/data/users.json +0 -70
- package/dist/scenarios/test-netflix/graph.json +0 -1017
- package/dist/scenarios/test-netflix/queries.d.ts +0 -29
- package/dist/scenarios/test-netflix/queries.d.ts.map +0 -1
- package/dist/scenarios/test-netflix/queries.js +0 -134
- package/dist/scenarios/test-netflix/queries.js.map +0 -1
- package/dist/scenarios/test-netflix/stack.json +0 -14
- package/dist/scripts/dictionary.json +0 -796
- package/dist/scripts/graph.json +0 -664
- package/dist/scripts/regenerate.d.ts +0 -23
- package/dist/scripts/regenerate.d.ts.map +0 -1
- package/dist/scripts/regenerate.js +0 -206
- package/dist/scripts/regenerate.js.map +0 -1
- package/src/scenarios/test-metro-paris/config.json +0 -6
- package/src/scenarios/test-metro-paris/graph.json +0 -16325
- package/src/scenarios/test-metro-paris/queries.ts +0 -152
- package/src/scenarios/test-metro-paris/stack.json +0 -1
- package/src/scenarios/test-musicians/config.json +0 -10
- package/src/scenarios/test-musicians/graph.json +0 -20
- package/src/scenarios/test-musicians/stack.json +0 -1
- package/src/scenarios/test-netflix/MIGRATION.md +0 -23
- package/src/scenarios/test-netflix/README.md +0 -138
- package/src/scenarios/test-netflix/actions.ts +0 -92
- package/src/scenarios/test-netflix/config.json +0 -6
- package/src/scenarios/test-netflix/data/categories.json +0 -1
- package/src/scenarios/test-netflix/data/companies.json +0 -1
- package/src/scenarios/test-netflix/data/credits.json +0 -19797
- package/src/scenarios/test-netflix/data/departments.json +0 -18
- package/src/scenarios/test-netflix/data/jobs.json +0 -142
- package/src/scenarios/test-netflix/data/movies.json +0 -3497
- package/src/scenarios/test-netflix/data/people.json +0 -1
- package/src/scenarios/test-netflix/data/synonyms.json +0 -8
- package/src/scenarios/test-netflix/data/users.json +0 -70
- package/src/scenarios/test-netflix/graph.json +0 -1017
- package/src/scenarios/test-netflix/queries.ts +0 -159
- package/src/scenarios/test-netflix/stack.json +0 -14
- package/src/scripts/dictionary.json +0 -796
- package/src/scripts/graph.json +0 -664
- package/src/scripts/regenerate.ts +0 -248
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* queries.ts — Requêtes métro Paris
|
|
3
|
-
*
|
|
4
|
-
* Remplace les config*.json éparpillés.
|
|
5
|
-
* Chaque requête a un nom, une description, et des paramètres typés.
|
|
6
|
-
*
|
|
7
|
-
* Usage :
|
|
8
|
-
* tsx cli/run-scenario.ts scenarios/test-metro-paris --query chatelet-opera
|
|
9
|
-
* tsx cli/run-scenario.ts scenarios/test-metro-paris --query all
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import type { PathQuery } from '../../types/index.js'
|
|
13
|
-
|
|
14
|
-
export interface NamedQuery {
|
|
15
|
-
name: string
|
|
16
|
-
description: string
|
|
17
|
-
query: PathQuery
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const metroQueries: NamedQuery[] = [
|
|
21
|
-
|
|
22
|
-
// ============================================================
|
|
23
|
-
// TRAJETS SIMPLES — Une seule ligne, pas de correspondance
|
|
24
|
-
// ============================================================
|
|
25
|
-
|
|
26
|
-
{
|
|
27
|
-
name: 'chatelet-opera',
|
|
28
|
-
description: 'Châtelet → Opéra (Ligne 7, 2 stations, ~3 min)',
|
|
29
|
-
query: {
|
|
30
|
-
from: 'Station-chatelet',
|
|
31
|
-
to: 'Station-opera',
|
|
32
|
-
maxPaths: 3
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
{
|
|
37
|
-
name: 'ligne1-terminus',
|
|
38
|
-
description: 'La Défense → Château de Vincennes (Ligne 1 complète, ~45 min)',
|
|
39
|
-
query: {
|
|
40
|
-
from: 'Station-la-defense-grande-arche',
|
|
41
|
-
to: 'Station-chateau-de-vincennes',
|
|
42
|
-
maxPaths: 1
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
{
|
|
47
|
-
name: 'ligne4-nord-sud',
|
|
48
|
-
description: 'Porte de Clignancourt → Mairie de Montrouge (Ligne 4 complète)',
|
|
49
|
-
query: {
|
|
50
|
-
from: 'Station-porte-de-clignancourt',
|
|
51
|
-
to: 'Station-mairie-de-montrouge',
|
|
52
|
-
maxPaths: 1
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
// ============================================================
|
|
57
|
-
// TRAJETS AVEC CORRESPONDANCES — Teste le pathfinder
|
|
58
|
-
// ============================================================
|
|
59
|
-
|
|
60
|
-
{
|
|
61
|
-
name: 'republique-bastille',
|
|
62
|
-
description: 'République → Bastille (plusieurs chemins via L5, L8, L9)',
|
|
63
|
-
query: {
|
|
64
|
-
from: 'Station-republique',
|
|
65
|
-
to: 'Station-bastille',
|
|
66
|
-
maxPaths: 5
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
{
|
|
71
|
-
name: 'gare-du-nord-montparnasse',
|
|
72
|
-
description: 'Gare du Nord → Montparnasse (correspondance obligatoire)',
|
|
73
|
-
query: {
|
|
74
|
-
from: 'Station-gare-du-nord',
|
|
75
|
-
to: 'Station-montparnasse-bienvenue',
|
|
76
|
-
maxPaths: 3
|
|
77
|
-
}
|
|
78
|
-
},
|
|
79
|
-
|
|
80
|
-
{
|
|
81
|
-
name: 'defense-nation',
|
|
82
|
-
description: 'La Défense → Nation (traversée Est-Ouest, Ligne 1)',
|
|
83
|
-
query: {
|
|
84
|
-
from: 'Station-la-defense-grande-arche',
|
|
85
|
-
to: 'Station-nation',
|
|
86
|
-
maxPaths: 3
|
|
87
|
-
}
|
|
88
|
-
},
|
|
89
|
-
|
|
90
|
-
// ============================================================
|
|
91
|
-
// TRAJETS COMPLEXES — Hubs majeurs, longue distance
|
|
92
|
-
// ============================================================
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
name: 'saint-denis-chatillon',
|
|
96
|
-
description: 'Saint-Denis Université → Châtillon-Montrouge (Ligne 13 complète)',
|
|
97
|
-
query: {
|
|
98
|
-
from: 'Station-saint-denis-universite',
|
|
99
|
-
to: 'Station-chatillon-montrouge',
|
|
100
|
-
maxPaths: 2
|
|
101
|
-
}
|
|
102
|
-
},
|
|
103
|
-
|
|
104
|
-
{
|
|
105
|
-
name: 'vincennes-defense',
|
|
106
|
-
description: 'Château de Vincennes → La Défense (traversée complète Ligne 1)',
|
|
107
|
-
query: {
|
|
108
|
-
from: 'Station-chateau-de-vincennes',
|
|
109
|
-
to: 'Station-la-defense-grande-arche',
|
|
110
|
-
maxPaths: 1
|
|
111
|
-
}
|
|
112
|
-
},
|
|
113
|
-
|
|
114
|
-
{
|
|
115
|
-
name: 'clignancourt-vincennes',
|
|
116
|
-
description: 'Porte de Clignancourt → Château de Vincennes (diagonale NW→SE)',
|
|
117
|
-
query: {
|
|
118
|
-
from: 'Station-porte-de-clignancourt',
|
|
119
|
-
to: 'Station-chateau-de-vincennes',
|
|
120
|
-
maxPaths: 5
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
|
|
124
|
-
// ============================================================
|
|
125
|
-
// TOURISME — Stations emblématiques
|
|
126
|
-
// ============================================================
|
|
127
|
-
|
|
128
|
-
{
|
|
129
|
-
name: 'louvre-tour-eiffel',
|
|
130
|
-
description: 'Louvre-Rivoli → Trocadéro (musées)',
|
|
131
|
-
query: {
|
|
132
|
-
from: 'Station-louvre-rivoli',
|
|
133
|
-
to: 'Station-trocadero',
|
|
134
|
-
maxPaths: 3
|
|
135
|
-
}
|
|
136
|
-
},
|
|
137
|
-
|
|
138
|
-
{
|
|
139
|
-
name: 'notre-dame-sacre-coeur',
|
|
140
|
-
description: 'Cité → Abbesses (Notre-Dame → Sacré-Cœur)',
|
|
141
|
-
query: {
|
|
142
|
-
from: 'Station-cite',
|
|
143
|
-
to: 'Station-abbesses',
|
|
144
|
-
maxPaths: 3
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
]
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Requête par défaut (utilisée sans --query)
|
|
151
|
-
*/
|
|
152
|
-
export const defaultQuery = metroQueries.find(q => q.name === 'chatelet-opera')!
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
[]
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"nodes": [
|
|
3
|
-
{ "id": "Artist-Manu-Dibango", "type": "entity" },
|
|
4
|
-
{ "id": "Artist-Michael-Jackson", "type": "entity" },
|
|
5
|
-
{ "id": "Artist-Will-Smith", "type": "entity" },
|
|
6
|
-
{ "id": "Track-Soul-Makossa", "type": "entity" },
|
|
7
|
-
{ "id": "Track-Wanna-Be-Startin", "type": "entity" },
|
|
8
|
-
{ "id": "Track-Gettin-Jiggy", "type": "entity" }
|
|
9
|
-
],
|
|
10
|
-
"edges": [
|
|
11
|
-
{ "name": "created", "from": "Artist-Manu-Dibango", "to": "Track-Soul-Makossa", "via": "artist_tracks", "weight": 1 },
|
|
12
|
-
{ "name": "created", "from": "Artist-Michael-Jackson", "to": "Track-Wanna-Be-Startin", "via": "artist_tracks", "weight": 1 },
|
|
13
|
-
{ "name": "created", "from": "Artist-Will-Smith", "to": "Track-Gettin-Jiggy", "via": "artist_tracks", "weight": 1 },
|
|
14
|
-
{ "name": "samples", "from": "Track-Wanna-Be-Startin", "to": "Track-Soul-Makossa", "via": "track_samples", "weight": 3 },
|
|
15
|
-
{ "name": "samples", "from": "Track-Gettin-Jiggy", "to": "Track-Wanna-Be-Startin", "via": "track_samples", "weight": 3 },
|
|
16
|
-
{ "name": "credited_on", "from": "Track-Soul-Makossa", "to": "Artist-Manu-Dibango", "via": "artist_tracks", "weight": 1 },
|
|
17
|
-
{ "name": "credited_on", "from": "Track-Wanna-Be-Startin", "to": "Artist-Michael-Jackson", "via": "artist_tracks", "weight": 1 },
|
|
18
|
-
{ "name": "credited_on", "from": "Track-Gettin-Jiggy", "to": "Artist-Will-Smith", "via": "artist_tracks", "weight": 1 }
|
|
19
|
-
]
|
|
20
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
[]
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# Migration depuis l'ancien scénario Netflix
|
|
2
|
-
|
|
3
|
-
## Fichiers supprimés
|
|
4
|
-
|
|
5
|
-
| Fichier | Raison |
|
|
6
|
-
|---------|--------|
|
|
7
|
-
| `actions.ts` | Mode SCHEDULE mis de côté — remplacé par `queries.ts` |
|
|
8
|
-
| `stack.json` | Pile pré-chargée pour SCHEDULE — plus pertinente |
|
|
9
|
-
|
|
10
|
-
## Fichiers remplacés
|
|
11
|
-
|
|
12
|
-
| Ancien | Nouveau | Changement |
|
|
13
|
-
|--------|---------|------------|
|
|
14
|
-
| `config.json` mode `SCHEDULE` | `config.json` mode `NAVIGATE` | Abandon de SCHEDULE |
|
|
15
|
-
| `graph.json` conceptuel (Directors/Actors/Genres) | `graph.json` généré par pipeline | Remplacement complet |
|
|
16
|
-
|
|
17
|
-
## Fichiers ajoutés
|
|
18
|
-
|
|
19
|
-
| Fichier | Description |
|
|
20
|
-
|---------|-------------|
|
|
21
|
-
| `data/` | 8 fichiers JSON + synonyms.json |
|
|
22
|
-
| `queries.ts` | 10 requêtes NAVIGATE/PATHFIND |
|
|
23
|
-
| `README.md` | Documentation complète |
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
# Scénario Netflix
|
|
2
|
-
|
|
3
|
-
Démonstration du **pipeline amont** de LinkLab sur des données JSON réelles.
|
|
4
|
-
|
|
5
|
-
Ce scénario est le seul qui illustre les deux côtés de LinkLab :
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
Pipeline amont JsonSchemaExtractor → SchemaAnalyzer → GraphBuilder
|
|
9
|
-
→ GraphAssembler → GraphOptimizer → graph.json
|
|
10
|
-
|
|
11
|
-
Pipeline aval PathFinder → NavigationEngine → résultats
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
Le `graph.json` de ce scénario **n'est pas écrit à la main** — il est généré
|
|
15
|
-
automatiquement depuis les 8 fichiers JSON dans `data/`.
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## Structure des données
|
|
20
|
-
|
|
21
|
-
```
|
|
22
|
-
data/
|
|
23
|
-
categories.json 18 entrées id, name
|
|
24
|
-
companies.json vide
|
|
25
|
-
credits.json 2 957 entrées id, movieId, personId, jobId
|
|
26
|
-
departments.json 4 entrées id, name
|
|
27
|
-
jobs.json 28 entrées id, name, departmentId
|
|
28
|
-
movies.json 200 entrées id, title, categories[], releaseYear, ...
|
|
29
|
-
people.json 2 363 entrées id, gender, name
|
|
30
|
-
users.json 5 entrées id, name, isAdmin, preferences{}
|
|
31
|
-
synonyms.json synonymes projet (person→people, movie→movies, ...)
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### Relations FK détectées automatiquement
|
|
35
|
-
|
|
36
|
-
| Colonne | Résolution | Stratégie |
|
|
37
|
-
|---------|------------|-----------|
|
|
38
|
-
| `credits.movieId` | → `movies.id` | pluriel régulier +s |
|
|
39
|
-
| `credits.personId` | → `people.id` | synonyme universel (person→people) |
|
|
40
|
-
| `credits.jobId` | → `jobs.id` | synonyme projet (job→jobs) |
|
|
41
|
-
| `jobs.departmentId` | → `departments.id` | correspondance directe |
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## Graphe généré
|
|
46
|
-
|
|
47
|
-
```
|
|
48
|
-
7 nœuds movies, people, credits, jobs, departments, categories, users
|
|
49
|
-
66 arêtes
|
|
50
|
-
physical × 4 FK déclarées
|
|
51
|
-
physical_reverse × 4 inverses automatiques
|
|
52
|
-
semantic_view × 56 movies ↔ people pour chacun des 28 jobs
|
|
53
|
-
virtual × 2 movies ↔ categories (array inline)
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### Pourquoi 56 vues sémantiques ?
|
|
57
|
-
|
|
58
|
-
`credits` est un pivot entre `movies` et `people` avec un discriminant `jobId → jobs`.
|
|
59
|
-
Le `GraphBuilder` lit la table `jobs` (28 entrées) et génère automatiquement une
|
|
60
|
-
paire d'arêtes sémantiques par job :
|
|
61
|
-
|
|
62
|
-
```
|
|
63
|
-
movies → people [actor] condition: { jobId: 1 }
|
|
64
|
-
people → movies [actor_in] condition: { jobId: 1 }
|
|
65
|
-
movies → people [director] condition: { jobId: 2 }
|
|
66
|
-
people → movies [director_in] condition: { jobId: 2 }
|
|
67
|
-
movies → people [writer] condition: { jobId: 3 }
|
|
68
|
-
...
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Sans le pipeline, ces 56 relations devraient être écrites à la main.
|
|
72
|
-
|
|
73
|
-
---
|
|
74
|
-
|
|
75
|
-
## Lancer le scénario
|
|
76
|
-
|
|
77
|
-
```bash
|
|
78
|
-
# Requête par défaut (directors-of-movie)
|
|
79
|
-
tsx cli/run-scenario.ts scenarios/test-netflix
|
|
80
|
-
|
|
81
|
-
# Requêtes disponibles
|
|
82
|
-
tsx cli/run-scenario.ts scenarios/test-netflix --query actors-of-movie
|
|
83
|
-
tsx cli/run-scenario.ts scenarios/test-netflix --query movies-of-director
|
|
84
|
-
tsx cli/run-scenario.ts scenarios/test-netflix --query movies-to-departments
|
|
85
|
-
tsx cli/run-scenario.ts scenarios/test-netflix --query people-to-movies-minhops
|
|
86
|
-
tsx cli/run-scenario.ts scenarios/test-netflix --query all
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### Requêtes disponibles
|
|
90
|
-
|
|
91
|
-
| Nom | Description |
|
|
92
|
-
|-----|-------------|
|
|
93
|
-
| `directors-of-movie` | movies → people via vue `director` |
|
|
94
|
-
| `actors-of-movie` | movies → people via vue `actor` |
|
|
95
|
-
| `movies-of-director` | people → movies via vue `director_in` |
|
|
96
|
-
| `movies-of-actor` | people → movies via vue `actor_in` |
|
|
97
|
-
| `credits-to-jobs` | navigation physique credits → jobs |
|
|
98
|
-
| `jobs-to-departments` | navigation physique jobs → departments |
|
|
99
|
-
| `movies-to-categories` | relation virtuelle (array inline) |
|
|
100
|
-
| `movies-to-departments` | 2 sauts : movies → credits → jobs → departments |
|
|
101
|
-
| `people-to-departments` | 3 sauts via credits → jobs → departments |
|
|
102
|
-
| `people-to-movies-minhops` | chemin le plus court avec `minHops` |
|
|
103
|
-
|
|
104
|
-
---
|
|
105
|
-
|
|
106
|
-
## Régénérer le graphe
|
|
107
|
-
|
|
108
|
-
Si tu modifies les données, relance le pipeline pour régénérer `graph.json` :
|
|
109
|
-
|
|
110
|
-
```bash
|
|
111
|
-
tsx cli/run-pipeline.ts scenarios/test-netflix/data --out scenarios/test-netflix/graph.json
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
Le pipeline utilise `data/synonyms.json` pour résoudre les FK irrégulières
|
|
115
|
-
(`personId → people`, `jobId → jobs`) en complément de `config/synonyms.json`
|
|
116
|
-
(synonymes universels).
|
|
117
|
-
|
|
118
|
-
---
|
|
119
|
-
|
|
120
|
-
## Ce que ce scénario ne couvre pas
|
|
121
|
-
|
|
122
|
-
| Donnée | Raison |
|
|
123
|
-
|--------|--------|
|
|
124
|
-
| `movies.categories` (array inline) | Relation virtuelle générée, mais sans garantie de correspondance exacte des ids |
|
|
125
|
-
| `users.preferences` (objet imbriqué) | Pas de FK — structure non relationnelle |
|
|
126
|
-
| `people/` et `movies/` (sous-dossiers détail) | Fichiers enrichis pour l'application — hors scope du pipeline |
|
|
127
|
-
| `companies.json` (vide) | Ignoré automatiquement |
|
|
128
|
-
|
|
129
|
-
---
|
|
130
|
-
|
|
131
|
-
## Comparaison avec les autres scénarios
|
|
132
|
-
|
|
133
|
-
| Scénario | Source | Ce qu'il démontre |
|
|
134
|
-
|----------|--------|-------------------|
|
|
135
|
-
| **Netflix** | JSON → pipeline | pipeline amont + vues sémantiques auto-générées |
|
|
136
|
-
| Musiciens | graph manuel | PATHFIND, `via`, `minHops`, cycles |
|
|
137
|
-
| Métro Paris | graph manuel | Dijkstra, poids, transferPenalty |
|
|
138
|
-
| DVDRental | PostgreSQL → pipeline | FK implicites, SchemaExtractor SQL |
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Actions du scénario Netflix
|
|
3
|
-
*
|
|
4
|
-
* Simule le parcours d'un utilisateur qui :
|
|
5
|
-
* 1. Voit la liste des films d'un réalisateur (déjà en contexte)
|
|
6
|
-
* 2. Sélectionne un film
|
|
7
|
-
* 3. Navigue vers les acteurs
|
|
8
|
-
* 4. Sélectionne un acteur
|
|
9
|
-
* 5. Explore les options à partir de cet acteur
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import type { ScheduleAction, Frame } from '../../types/index.js'
|
|
13
|
-
|
|
14
|
-
const actions: ScheduleAction[] = [
|
|
15
|
-
{
|
|
16
|
-
name: 'selectMovie',
|
|
17
|
-
weight: 10,
|
|
18
|
-
// Movies est résolu (liste chargée) mais pas encore d'ID choisi
|
|
19
|
-
when: (stack: Frame[]) => {
|
|
20
|
-
const movies = stack.find(f => f.entity === 'Movies')
|
|
21
|
-
return movies?.state === 'RESOLVED' && movies.id == null
|
|
22
|
-
},
|
|
23
|
-
execute: async (stack: Frame[]) => {
|
|
24
|
-
console.log(' 🎬 [selectMovie] L\'utilisateur choisit un film dans la liste...')
|
|
25
|
-
const movies = stack.find(f => f.entity === 'Movies')
|
|
26
|
-
if (movies) {
|
|
27
|
-
movies.id = 10
|
|
28
|
-
console.log(' ✓ Film #10 sélectionné')
|
|
29
|
-
}
|
|
30
|
-
return stack
|
|
31
|
-
},
|
|
32
|
-
cooldown: 0
|
|
33
|
-
},
|
|
34
|
-
|
|
35
|
-
{
|
|
36
|
-
name: 'navigateToActors',
|
|
37
|
-
weight: 8,
|
|
38
|
-
// Un film est sélectionné, mais pas encore de frame Actors
|
|
39
|
-
when: (stack: Frame[]) => {
|
|
40
|
-
const movies = stack.find(f => f.entity === 'Movies')
|
|
41
|
-
const actors = stack.find(f => f.entity === 'Actors')
|
|
42
|
-
return !!movies && movies.id != null && !actors
|
|
43
|
-
},
|
|
44
|
-
execute: async (stack: Frame[]) => {
|
|
45
|
-
console.log(' 🎭 [navigateToActors] L\'utilisateur clique sur "Voir les acteurs"...')
|
|
46
|
-
stack.push({ entity: 'Actors', state: 'UNRESOLVED' })
|
|
47
|
-
console.log(' ✓ Frame Actors ajoutée à la stack')
|
|
48
|
-
return stack
|
|
49
|
-
},
|
|
50
|
-
cooldown: 0
|
|
51
|
-
},
|
|
52
|
-
|
|
53
|
-
{
|
|
54
|
-
name: 'selectActor',
|
|
55
|
-
weight: 5,
|
|
56
|
-
// Actors existe, est résolu, mais pas encore d'ID choisi
|
|
57
|
-
when: (stack: Frame[]) => {
|
|
58
|
-
const actors = stack.find(f => f.entity === 'Actors')
|
|
59
|
-
return !!actors && actors.state === 'RESOLVED' && actors.id == null
|
|
60
|
-
},
|
|
61
|
-
execute: async (stack: Frame[]) => {
|
|
62
|
-
console.log(' ⭐ [selectActor] L\'utilisateur sélectionne un acteur...')
|
|
63
|
-
const actors = stack.find(f => f.entity === 'Actors')
|
|
64
|
-
if (actors) {
|
|
65
|
-
actors.id = 3
|
|
66
|
-
console.log(' ✓ Acteur #3 sélectionné')
|
|
67
|
-
}
|
|
68
|
-
return stack
|
|
69
|
-
},
|
|
70
|
-
cooldown: 0
|
|
71
|
-
},
|
|
72
|
-
|
|
73
|
-
{
|
|
74
|
-
name: 'exploreFromActor',
|
|
75
|
-
weight: 3,
|
|
76
|
-
terminal: true, // S'exécute une seule fois
|
|
77
|
-
when: (stack: Frame[]) => {
|
|
78
|
-
const actors = stack.find(f => f.entity === 'Actors')
|
|
79
|
-
return !!actors && actors.id != null
|
|
80
|
-
},
|
|
81
|
-
execute: async (stack: Frame[]) => {
|
|
82
|
-
console.log(' 🔍 [exploreFromActor] Affichage des options d\'exploration :')
|
|
83
|
-
console.log(' - Filmographie complète')
|
|
84
|
-
console.log(' - Autres réalisateurs')
|
|
85
|
-
console.log(' - Co-stars')
|
|
86
|
-
return stack
|
|
87
|
-
},
|
|
88
|
-
cooldown: 0
|
|
89
|
-
}
|
|
90
|
-
]
|
|
91
|
-
|
|
92
|
-
export default actions
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"mode": "NAVIGATE",
|
|
3
|
-
"description": "Scénario Netflix — navigation dans un graphe généré automatiquement par le pipeline. Démontre les vues sémantiques (actor, director, writer...) issues de credits.jobId → jobs.",
|
|
4
|
-
"dataPath": "./data",
|
|
5
|
-
"graphGeneratedBy": "JsonSchemaExtractor → SchemaAnalyzer → GraphBuilder → GraphAssembler → GraphOptimizer"
|
|
6
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
[{"id":18,"name":"Drame"},{"id":80,"name":"Crime"},{"id":36,"name":"Histoire"},{"id":10752,"name":"Guerre"},{"id":35,"name":"Comédie"},{"id":10749,"name":"Romance"},{"id":16,"name":"Animation"},{"id":10751,"name":"Familial"},{"id":14,"name":"Fantastique"},{"id":28,"name":"Action"},{"id":53,"name":"Thriller"},{"id":12,"name":"Aventure"},{"id":37,"name":"Western"},{"id":10402,"name":"Musique"},{"id":27,"name":"Horreur"},{"id":9648,"name":"Mystère"},{"id":878,"name":"Science-Fiction"},{"id":10770,"name":"Téléfilm"}]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
[]
|