diff --git a/public/strategie-script.js b/public/strategie-script.js index ee57859..2d9fad4 100644 --- a/public/strategie-script.js +++ b/public/strategie-script.js @@ -916,6 +916,19 @@ Interface de pilotage pour les responsables sécurité des PME. container = linkContainer; } + // Ajouter le lien vers la page Équipe + if (!document.getElementById('link-team')) { + const teamLink = document.createElement('a'); + teamLink.id = 'link-team'; + teamLink.className = 'custom-nav-link'; + teamLink.href = '/team.html'; + teamLink.textContent = '👥 Équipe'; + teamLink.style.cssText = 'color: #2ecc71; text-decoration: none; font-weight: bold; cursor: pointer; font-size: 14px; padding: 5px 8px; border-radius: 4px; transition: background 0.2s;'; + teamLink.addEventListener('mouseenter', () => teamLink.style.background = 'rgba(46, 204, 113, 0.1)'); + teamLink.addEventListener('mouseleave', () => teamLink.style.background = 'transparent'); + container.appendChild(teamLink); + } + // Ajouter les liens Object.keys(pageTitles).forEach(key => { if (document.getElementById(`link-${key}`)) return; diff --git a/public/team-visualization-data.json b/public/team-visualization-data.json new file mode 100644 index 0000000..7bea4aa --- /dev/null +++ b/public/team-visualization-data.json @@ -0,0 +1,1749 @@ +{ + "network": { + "nodes": [ + { + "data": { + "id": "tech-3node", + "label": "3Node", + "type": "technology", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "coverage": 0, + "businessImpact": "high", + "skillGap": "high", + "color": "#ff8800" + } + }, + { + "data": { + "id": "tech-aibox", + "label": "AIBox", + "type": "technology", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "coverage": 1, + "businessImpact": "high", + "skillGap": "high", + "color": "#ff8800" + } + }, + { + "data": { + "id": "tech-ansible", + "label": "Ansible", + "type": "technology", + "ring": "trial", + "quadrant": "technologies-emergentes", + "coverage": 0, + "businessImpact": "high", + "skillGap": "high", + "color": "#999999" + } + }, + { + "data": { + "id": "tech-bash", + "label": "Bash", + "type": "technology", + "ring": "support", + "quadrant": "technologies-commodite", + "coverage": 1, + "businessImpact": "medium", + "skillGap": "high", + "color": "#4488ff" + } + }, + { + "data": { + "id": "tech-cryptographie", + "label": "Cryptographie", + "type": "technology", + "ring": "support", + "quadrant": "technologies-commodite", + "coverage": 1, + "businessImpact": "medium", + "skillGap": "high", + "color": "#4488ff" + } + }, + { + "data": { + "id": "tech-cytoscape-js", + "label": "Cytoscape.js", + "type": "technology", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "coverage": 1, + "businessImpact": "high", + "skillGap": "high", + "color": "#ff8800" + } + }, + { + "data": { + "id": "tech-d3-js", + "label": "D3.js", + "type": "technology", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "coverage": 2, + "businessImpact": "high", + "skillGap": "medium", + "color": "#ff8800" + } + }, + { + "data": { + "id": "tech-dart", + "label": "Dart", + "type": "technology", + "ring": "support", + "quadrant": "technologies-commodite", + "coverage": 1, + "businessImpact": "medium", + "skillGap": "high", + "color": "#4488ff" + } + }, + { + "data": { + "id": "tech-docker", + "label": "Docker", + "type": "technology", + "ring": "support", + "quadrant": "technologies-commodite", + "coverage": 1, + "businessImpact": "medium", + "skillGap": "high", + "color": "#4488ff" + } + }, + { + "data": { + "id": "tech-echarts", + "label": "ECharts", + "type": "technology", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "coverage": 0, + "businessImpact": "high", + "skillGap": "high", + "color": "#ff8800" + } + }, + { + "data": { + "id": "tech-flutter", + "label": "Flutter", + "type": "technology", + "ring": "support", + "quadrant": "technologies-commodite", + "coverage": 1, + "businessImpact": "medium", + "skillGap": "high", + "color": "#4488ff" + } + }, + { + "data": { + "id": "tech-gitlab-ci-cd", + "label": "GitLab CI/CD", + "type": "technology", + "ring": "support", + "quadrant": "technologies-commodite", + "coverage": 1, + "businessImpact": "medium", + "skillGap": "high", + "color": "#4488ff" + } + }, + { + "data": { + "id": "tech-grafana", + "label": "Grafana", + "type": "technology", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "coverage": 0, + "businessImpact": "high", + "skillGap": "high", + "color": "#ff8800" + } + }, + { + "data": { + "id": "tech-ipfs", + "label": "IPFS", + "type": "technology", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "coverage": 2, + "businessImpact": "high", + "skillGap": "medium", + "color": "#ff8800" + } + }, + { + "data": { + "id": "tech-javascript-typescript", + "label": "JavaScript/TypeScript", + "type": "technology", + "ring": "support", + "quadrant": "technologies-commodite", + "coverage": 3, + "businessImpact": "medium", + "skillGap": "low", + "color": "#4488ff" + } + }, + { + "data": { + "id": "tech-kubernetes", + "label": "Kubernetes", + "type": "technology", + "ring": "support", + "quadrant": "technologies-commodite", + "coverage": 0, + "businessImpact": "medium", + "skillGap": "high", + "color": "#4488ff" + } + }, + { + "data": { + "id": "tech-leaflet", + "label": "Leaflet", + "type": "technology", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "coverage": 0, + "businessImpact": "high", + "skillGap": "high", + "color": "#ff8800" + } + }, + { + "data": { + "id": "tech-linux", + "label": "Linux", + "type": "technology", + "ring": "support", + "quadrant": "technologies-commodite", + "coverage": 2, + "businessImpact": "medium", + "skillGap": "medium", + "color": "#4488ff" + } + }, + { + "data": { + "id": "tech-mycelium-network", + "label": "Mycelium Network", + "type": "technology", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "coverage": 0, + "businessImpact": "high", + "skillGap": "high", + "color": "#ff8800" + } + }, + { + "data": { + "id": "tech-netlifycms", + "label": "NetlifyCMS", + "type": "technology", + "ring": "support", + "quadrant": "technologies-commodite", + "coverage": 2, + "businessImpact": "medium", + "skillGap": "medium", + "color": "#4488ff" + } + }, + { + "data": { + "id": "tech-nostr", + "label": "Nostr", + "type": "technology", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "coverage": 1, + "businessImpact": "high", + "skillGap": "high", + "color": "#ff8800" + } + }, + { + "data": { + "id": "tech-nuxt-js", + "label": "Nuxt.js", + "type": "technology", + "ring": "support", + "quadrant": "technologies-commodite", + "coverage": 2, + "businessImpact": "medium", + "skillGap": "medium", + "color": "#4488ff" + } + }, + { + "data": { + "id": "tech-opentofu", + "label": "OpenTofu", + "type": "technology", + "ring": "trial", + "quadrant": "technologies-emergentes", + "coverage": 0, + "businessImpact": "high", + "skillGap": "high", + "color": "#999999" + } + }, + { + "data": { + "id": "tech-postgresql", + "label": "PostgreSQL", + "type": "technology", + "ring": "support", + "quadrant": "technologies-commodite", + "coverage": 0, + "businessImpact": "medium", + "skillGap": "high", + "color": "#4488ff" + } + }, + { + "data": { + "id": "tech-proxmox", + "label": "ProxMox", + "type": "technology", + "ring": "support", + "quadrant": "technologies-commodite", + "coverage": 1, + "businessImpact": "medium", + "skillGap": "high", + "color": "#4488ff" + } + }, + { + "data": { + "id": "tech-python", + "label": "Python", + "type": "technology", + "ring": "support", + "quadrant": "technologies-commodite", + "coverage": 1, + "businessImpact": "medium", + "skillGap": "high", + "color": "#4488ff" + } + }, + { + "data": { + "id": "tech-rust", + "label": "Rust", + "type": "technology", + "ring": "core", + "quadrant": "technologies-differentiantes", + "coverage": 1, + "businessImpact": "high", + "skillGap": "high", + "color": "#ff4444" + } + }, + { + "data": { + "id": "tech-serverless", + "label": "Serverless", + "type": "technology", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "coverage": 1, + "businessImpact": "high", + "skillGap": "high", + "color": "#ff8800" + } + }, + { + "data": { + "id": "tech-squid", + "label": "Squid", + "type": "technology", + "ring": "support", + "quadrant": "technologies-commodite", + "coverage": 1, + "businessImpact": "medium", + "skillGap": "high", + "color": "#4488ff" + } + }, + { + "data": { + "id": "tech-substrate-framework", + "label": "Substrate Framework", + "type": "technology", + "ring": "core", + "quadrant": "technologies-differentiantes", + "coverage": 1, + "businessImpact": "high", + "skillGap": "high", + "color": "#ff4444" + } + }, + { + "data": { + "id": "tech-threefold-blockchain", + "label": "ThreeFold Blockchain", + "type": "technology", + "ring": "core", + "quadrant": "technologies-differentiantes", + "coverage": 3, + "businessImpact": "high", + "skillGap": "low", + "color": "#ff4444" + } + }, + { + "data": { + "id": "tech-threefold-cloud", + "label": "ThreeFold Cloud", + "type": "technology", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "coverage": 2, + "businessImpact": "high", + "skillGap": "medium", + "color": "#ff8800" + } + }, + { + "data": { + "id": "tech-threefold-compute", + "label": "ThreeFold Compute", + "type": "technology", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "coverage": 2, + "businessImpact": "high", + "skillGap": "medium", + "color": "#ff8800" + } + }, + { + "data": { + "id": "tech-threefold-data-storage", + "label": "ThreeFold Data Storage", + "type": "technology", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "coverage": 2, + "businessImpact": "high", + "skillGap": "medium", + "color": "#ff8800" + } + }, + { + "data": { + "id": "tech-threefold-grid", + "label": "ThreeFold Grid", + "type": "technology", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "coverage": 4, + "businessImpact": "high", + "skillGap": "low", + "color": "#ff8800" + } + }, + { + "data": { + "id": "tech-vue-js", + "label": "Vue.js", + "type": "technology", + "ring": "support", + "quadrant": "technologies-commodite", + "coverage": 2, + "businessImpact": "medium", + "skillGap": "medium", + "color": "#4488ff" + } + }, + { + "data": { + "id": "tech-wordup-cms", + "label": "WordUp CMS", + "type": "technology", + "ring": "support", + "quadrant": "technologies-commodite", + "coverage": 1, + "businessImpact": "medium", + "skillGap": "high", + "color": "#4488ff" + } + }, + { + "data": { + "id": "tech-zero-os", + "label": "Zero OS", + "type": "technology", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "coverage": 0, + "businessImpact": "high", + "skillGap": "high", + "color": "#ff8800" + } + }, + { + "data": { + "id": "member-1000i100", + "label": "1000i100", + "type": "member", + "availability": 50, + "seniority": "expert", + "role": "DevOps & Développeur Web" + } + }, + { + "data": { + "id": "member-aya", + "label": "aya", + "type": "member", + "availability": 30, + "seniority": "expert", + "role": "Administrateur Système & Infrastructure Distribuée" + } + }, + { + "data": { + "id": "member-boris", + "label": "boris", + "type": "member", + "availability": 40, + "seniority": "intermediate", + "role": "UX/UI Designer & Développeur Full Stack" + } + }, + { + "data": { + "id": "member-elois", + "label": "Eloïs", + "type": "member", + "availability": 25, + "seniority": "expert", + "role": "Développeur Blockchain" + } + }, + { + "data": { + "id": "member-fred", + "label": "Fred", + "type": "member", + "availability": 40, + "seniority": "expert", + "role": "Développeur & Architecte Systèmes Décentralisés" + } + }, + { + "data": { + "id": "member-hugo", + "label": "Hugo Trentesaux", + "type": "member", + "availability": 20, + "seniority": "intermediate", + "role": "Financement & Gestion" + } + }, + { + "data": { + "id": "member-manuTopik", + "label": "ManUtopiK", + "type": "member", + "availability": 40, + "seniority": "expert", + "role": "Développeur Web Full Stack" + } + }, + { + "data": { + "id": "member-poka", + "label": "Poka", + "type": "member", + "availability": 50, + "seniority": "expert", + "role": "Développeur Full Stack & Administrateur Système" + } + }, + { + "data": { + "id": "member-syoul", + "label": "Syoul", + "type": "member", + "availability": 30, + "seniority": "intermediate", + "role": "Artisan Libriste & Animateur" + } + }, + { + "data": { + "id": "member-tuxmain", + "label": "tuxmain", + "type": "member", + "availability": 20, + "seniority": "beginner", + "role": "Étudiant Math & Cryptographie" + } + }, + { + "data": { + "id": "member-vivien", + "label": "Vivien", + "type": "member", + "availability": 30, + "seniority": "beginner", + "role": "Développeur" + } + }, + { + "data": { + "id": "member-yvv", + "label": "Yvv", + "type": "member", + "availability": 20, + "seniority": "senior", + "role": "Gestion & Mobilisation" + } + } + ], + "edges": [ + { + "data": { + "id": "edge-aibox-yvv", + "source": "tech-aibox", + "target": "member-yvv", + "weight": 0.5 + } + }, + { + "data": { + "id": "edge-bash-poka", + "source": "tech-bash", + "target": "member-poka", + "weight": 1 + } + }, + { + "data": { + "id": "edge-cryptographie-tuxmain", + "source": "tech-cryptographie", + "target": "member-tuxmain", + "weight": 1 + } + }, + { + "data": { + "id": "edge-cytoscape-js-boris", + "source": "tech-cytoscape-js", + "target": "member-boris", + "weight": 0.5 + } + }, + { + "data": { + "id": "edge-d3-js-boris", + "source": "tech-d3-js", + "target": "member-boris", + "weight": 0.5 + } + }, + { + "data": { + "id": "edge-d3-js-manuTopik", + "source": "tech-d3-js", + "target": "member-manuTopik", + "weight": 0.5 + } + }, + { + "data": { + "id": "edge-dart-poka", + "source": "tech-dart", + "target": "member-poka", + "weight": 1 + } + }, + { + "data": { + "id": "edge-docker-1000i100", + "source": "tech-docker", + "target": "member-1000i100", + "weight": 1 + } + }, + { + "data": { + "id": "edge-flutter-poka", + "source": "tech-flutter", + "target": "member-poka", + "weight": 1 + } + }, + { + "data": { + "id": "edge-gitlab-ci-cd-1000i100", + "source": "tech-gitlab-ci-cd", + "target": "member-1000i100", + "weight": 1 + } + }, + { + "data": { + "id": "edge-ipfs-aya", + "source": "tech-ipfs", + "target": "member-aya", + "weight": 1 + } + }, + { + "data": { + "id": "edge-ipfs-fred", + "source": "tech-ipfs", + "target": "member-fred", + "weight": 1 + } + }, + { + "data": { + "id": "edge-javascript-typescript-1000i100", + "source": "tech-javascript-typescript", + "target": "member-1000i100", + "weight": 0.5 + } + }, + { + "data": { + "id": "edge-javascript-typescript-boris", + "source": "tech-javascript-typescript", + "target": "member-boris", + "weight": 1 + } + }, + { + "data": { + "id": "edge-javascript-typescript-manuTopik", + "source": "tech-javascript-typescript", + "target": "member-manuTopik", + "weight": 1 + } + }, + { + "data": { + "id": "edge-linux-aya", + "source": "tech-linux", + "target": "member-aya", + "weight": 1 + } + }, + { + "data": { + "id": "edge-linux-boris", + "source": "tech-linux", + "target": "member-boris", + "weight": 1 + } + }, + { + "data": { + "id": "edge-netlifycms-1000i100", + "source": "tech-netlifycms", + "target": "member-1000i100", + "weight": 0.5 + } + }, + { + "data": { + "id": "edge-netlifycms-manuTopik", + "source": "tech-netlifycms", + "target": "member-manuTopik", + "weight": 1 + } + }, + { + "data": { + "id": "edge-nostr-fred", + "source": "tech-nostr", + "target": "member-fred", + "weight": 1 + } + }, + { + "data": { + "id": "edge-nuxt-js-boris", + "source": "tech-nuxt-js", + "target": "member-boris", + "weight": 1 + } + }, + { + "data": { + "id": "edge-nuxt-js-manuTopik", + "source": "tech-nuxt-js", + "target": "member-manuTopik", + "weight": 1 + } + }, + { + "data": { + "id": "edge-proxmox-poka", + "source": "tech-proxmox", + "target": "member-poka", + "weight": 1 + } + }, + { + "data": { + "id": "edge-python-poka", + "source": "tech-python", + "target": "member-poka", + "weight": 1 + } + }, + { + "data": { + "id": "edge-rust-elois", + "source": "tech-rust", + "target": "member-elois", + "weight": 1 + } + }, + { + "data": { + "id": "edge-serverless-1000i100", + "source": "tech-serverless", + "target": "member-1000i100", + "weight": 1 + } + }, + { + "data": { + "id": "edge-squid-boris", + "source": "tech-squid", + "target": "member-boris", + "weight": 1 + } + }, + { + "data": { + "id": "edge-substrate-framework-elois", + "source": "tech-substrate-framework", + "target": "member-elois", + "weight": 1 + } + }, + { + "data": { + "id": "edge-threefold-blockchain-aya", + "source": "tech-threefold-blockchain", + "target": "member-aya", + "weight": 1 + } + }, + { + "data": { + "id": "edge-threefold-blockchain-elois", + "source": "tech-threefold-blockchain", + "target": "member-elois", + "weight": 1 + } + }, + { + "data": { + "id": "edge-threefold-blockchain-fred", + "source": "tech-threefold-blockchain", + "target": "member-fred", + "weight": 1 + } + }, + { + "data": { + "id": "edge-threefold-cloud-aya", + "source": "tech-threefold-cloud", + "target": "member-aya", + "weight": 1 + } + }, + { + "data": { + "id": "edge-threefold-cloud-fred", + "source": "tech-threefold-cloud", + "target": "member-fred", + "weight": 1 + } + }, + { + "data": { + "id": "edge-threefold-compute-aya", + "source": "tech-threefold-compute", + "target": "member-aya", + "weight": 1 + } + }, + { + "data": { + "id": "edge-threefold-compute-fred", + "source": "tech-threefold-compute", + "target": "member-fred", + "weight": 1 + } + }, + { + "data": { + "id": "edge-threefold-data-storage-aya", + "source": "tech-threefold-data-storage", + "target": "member-aya", + "weight": 1 + } + }, + { + "data": { + "id": "edge-threefold-data-storage-fred", + "source": "tech-threefold-data-storage", + "target": "member-fred", + "weight": 1 + } + }, + { + "data": { + "id": "edge-threefold-grid-aya", + "source": "tech-threefold-grid", + "target": "member-aya", + "weight": 1 + } + }, + { + "data": { + "id": "edge-threefold-grid-fred", + "source": "tech-threefold-grid", + "target": "member-fred", + "weight": 1 + } + }, + { + "data": { + "id": "edge-threefold-grid-poka", + "source": "tech-threefold-grid", + "target": "member-poka", + "weight": 0.5 + } + }, + { + "data": { + "id": "edge-threefold-grid-syoul", + "source": "tech-threefold-grid", + "target": "member-syoul", + "weight": 0.5 + } + }, + { + "data": { + "id": "edge-vue-js-boris", + "source": "tech-vue-js", + "target": "member-boris", + "weight": 0.5 + } + }, + { + "data": { + "id": "edge-vue-js-manuTopik", + "source": "tech-vue-js", + "target": "member-manuTopik", + "weight": 0.5 + } + }, + { + "data": { + "id": "edge-wordup-cms-manuTopik", + "source": "tech-wordup-cms", + "target": "member-manuTopik", + "weight": 1 + } + } + ] + }, + "congestionMatrix": [ + { + "technology": "Rust", + "technologyId": "rust", + "businessImpact": "high", + "coverage": 1, + "skillGap": "high", + "members": [ + { + "member": "1000i100", + "fullName": "1000i100", + "hasSkill": false, + "availability": 50, + "seniority": "expert" + }, + { + "member": "poka", + "fullName": "Poka", + "hasSkill": false, + "availability": 50, + "seniority": "expert" + } + ] + }, + { + "technology": "Substrate Framework", + "technologyId": "substrate-framework", + "businessImpact": "high", + "coverage": 1, + "skillGap": "high", + "members": [ + { + "member": "1000i100", + "fullName": "1000i100", + "hasSkill": false, + "availability": 50, + "seniority": "expert" + }, + { + "member": "poka", + "fullName": "Poka", + "hasSkill": false, + "availability": 50, + "seniority": "expert" + } + ] + }, + { + "technology": "ThreeFold Blockchain", + "technologyId": "threefold-blockchain", + "businessImpact": "high", + "coverage": 3, + "skillGap": "low", + "members": [ + { + "member": "1000i100", + "fullName": "1000i100", + "hasSkill": false, + "availability": 50, + "seniority": "expert" + }, + { + "member": "poka", + "fullName": "Poka", + "hasSkill": false, + "availability": 50, + "seniority": "expert" + } + ] + } + ], + "genesisTeam": { + "team": [], + "totalMembers": 0, + "coveredTechnologies": 0, + "totalCoreTechnologies": 3, + "uncoveredTechnologies": [ + { + "id": "rust", + "title": "Rust", + "businessImpact": "high", + "skillGap": "high", + "teamCoverage": 1 + }, + { + "id": "substrate-framework", + "title": "Substrate Framework", + "businessImpact": "high", + "skillGap": "high", + "teamCoverage": 1 + }, + { + "id": "threefold-blockchain", + "title": "ThreeFold Blockchain", + "businessImpact": "high", + "skillGap": "low", + "teamCoverage": 3 + } + ], + "totalCapacity": 0, + "averageAvailability": 0 + }, + "technologies": [ + { + "id": "3node", + "title": "3Node", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 0, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [] + }, + { + "id": "aibox", + "title": "AIBox", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 1, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [ + "yvv" + ] + }, + { + "id": "ansible", + "title": "Ansible", + "ring": "trial", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 0, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [] + }, + { + "id": "bash", + "title": "Bash", + "ring": "support", + "quadrant": "technologies-commodite", + "businessImpact": "medium", + "teamCoverage": 1, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [ + "poka" + ] + }, + { + "id": "cryptographie", + "title": "Cryptographie", + "ring": "support", + "quadrant": "technologies-commodite", + "businessImpact": "medium", + "teamCoverage": 1, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [ + "tuxmain" + ] + }, + { + "id": "cytoscape-js", + "title": "Cytoscape.js", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 1, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [ + "boris" + ] + }, + { + "id": "d3-js", + "title": "D3.js", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 2, + "skillGap": "medium", + "competencyLevel": "intermediate", + "members": [ + "boris", + "manuTopik" + ] + }, + { + "id": "dart", + "title": "Dart", + "ring": "support", + "quadrant": "technologies-commodite", + "businessImpact": "medium", + "teamCoverage": 1, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [ + "poka" + ] + }, + { + "id": "docker", + "title": "Docker", + "ring": "support", + "quadrant": "technologies-commodite", + "businessImpact": "medium", + "teamCoverage": 1, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [ + "1000i100" + ] + }, + { + "id": "echarts", + "title": "ECharts", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 0, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [] + }, + { + "id": "flutter", + "title": "Flutter", + "ring": "support", + "quadrant": "technologies-commodite", + "businessImpact": "medium", + "teamCoverage": 1, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [ + "poka" + ] + }, + { + "id": "gitlab-ci-cd", + "title": "GitLab CI/CD", + "ring": "support", + "quadrant": "technologies-commodite", + "businessImpact": "medium", + "teamCoverage": 1, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [ + "1000i100" + ] + }, + { + "id": "grafana", + "title": "Grafana", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 0, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [] + }, + { + "id": "ipfs", + "title": "IPFS", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 2, + "skillGap": "medium", + "competencyLevel": "intermediate", + "members": [ + "aya", + "fred" + ] + }, + { + "id": "javascript-typescript", + "title": "JavaScript/TypeScript", + "ring": "support", + "quadrant": "technologies-commodite", + "businessImpact": "medium", + "teamCoverage": 3, + "skillGap": "low", + "competencyLevel": "expert", + "members": [ + "1000i100", + "boris", + "manuTopik" + ] + }, + { + "id": "kubernetes", + "title": "Kubernetes", + "ring": "support", + "quadrant": "technologies-commodite", + "businessImpact": "medium", + "teamCoverage": 0, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [] + }, + { + "id": "leaflet", + "title": "Leaflet", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 0, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [] + }, + { + "id": "linux", + "title": "Linux", + "ring": "support", + "quadrant": "technologies-commodite", + "businessImpact": "medium", + "teamCoverage": 2, + "skillGap": "medium", + "competencyLevel": "intermediate", + "members": [ + "aya", + "boris" + ] + }, + { + "id": "mycelium-network", + "title": "Mycelium Network", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 0, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [] + }, + { + "id": "netlifycms", + "title": "NetlifyCMS", + "ring": "support", + "quadrant": "technologies-commodite", + "businessImpact": "medium", + "teamCoverage": 2, + "skillGap": "medium", + "competencyLevel": "intermediate", + "members": [ + "1000i100", + "manuTopik" + ] + }, + { + "id": "nostr", + "title": "Nostr", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 1, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [ + "fred" + ] + }, + { + "id": "nuxt-js", + "title": "Nuxt.js", + "ring": "support", + "quadrant": "technologies-commodite", + "businessImpact": "medium", + "teamCoverage": 2, + "skillGap": "medium", + "competencyLevel": "intermediate", + "members": [ + "boris", + "manuTopik" + ] + }, + { + "id": "opentofu", + "title": "OpenTofu", + "ring": "trial", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 0, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [] + }, + { + "id": "postgresql", + "title": "PostgreSQL", + "ring": "support", + "quadrant": "technologies-commodite", + "businessImpact": "medium", + "teamCoverage": 0, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [] + }, + { + "id": "proxmox", + "title": "ProxMox", + "ring": "support", + "quadrant": "technologies-commodite", + "businessImpact": "medium", + "teamCoverage": 1, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [ + "poka" + ] + }, + { + "id": "python", + "title": "Python", + "ring": "support", + "quadrant": "technologies-commodite", + "businessImpact": "medium", + "teamCoverage": 1, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [ + "poka" + ] + }, + { + "id": "rust", + "title": "Rust", + "ring": "core", + "quadrant": "technologies-differentiantes", + "businessImpact": "high", + "teamCoverage": 1, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [ + "elois" + ] + }, + { + "id": "serverless", + "title": "Serverless", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 1, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [ + "1000i100" + ] + }, + { + "id": "squid", + "title": "Squid", + "ring": "support", + "quadrant": "technologies-commodite", + "businessImpact": "medium", + "teamCoverage": 1, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [ + "boris" + ] + }, + { + "id": "substrate-framework", + "title": "Substrate Framework", + "ring": "core", + "quadrant": "technologies-differentiantes", + "businessImpact": "high", + "teamCoverage": 1, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [ + "elois" + ] + }, + { + "id": "threefold-blockchain", + "title": "ThreeFold Blockchain", + "ring": "core", + "quadrant": "technologies-differentiantes", + "businessImpact": "high", + "teamCoverage": 3, + "skillGap": "low", + "competencyLevel": "expert", + "members": [ + "aya", + "elois", + "fred" + ] + }, + { + "id": "threefold-cloud", + "title": "ThreeFold Cloud", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 2, + "skillGap": "medium", + "competencyLevel": "intermediate", + "members": [ + "aya", + "fred" + ] + }, + { + "id": "threefold-compute", + "title": "ThreeFold Compute", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 2, + "skillGap": "medium", + "competencyLevel": "intermediate", + "members": [ + "aya", + "fred" + ] + }, + { + "id": "threefold-data-storage", + "title": "ThreeFold Data Storage", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 2, + "skillGap": "medium", + "competencyLevel": "intermediate", + "members": [ + "aya", + "fred" + ] + }, + { + "id": "threefold-grid", + "title": "ThreeFold Grid", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 4, + "skillGap": "low", + "competencyLevel": "expert", + "members": [ + "aya", + "fred", + "poka", + "syoul" + ] + }, + { + "id": "vue-js", + "title": "Vue.js", + "ring": "support", + "quadrant": "technologies-commodite", + "businessImpact": "medium", + "teamCoverage": 2, + "skillGap": "medium", + "competencyLevel": "intermediate", + "members": [ + "boris", + "manuTopik" + ] + }, + { + "id": "wordup-cms", + "title": "WordUp CMS", + "ring": "support", + "quadrant": "technologies-commodite", + "businessImpact": "medium", + "teamCoverage": 1, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [ + "manuTopik" + ] + }, + { + "id": "zero-os", + "title": "Zero OS", + "ring": "strategic", + "quadrant": "technologies-emergentes", + "businessImpact": "high", + "teamCoverage": 0, + "skillGap": "high", + "competencyLevel": "beginner", + "members": [] + } + ], + "members": [ + { + "id": "1000i100", + "fullName": "1000i100", + "role": "DevOps & Développeur Web", + "availability": 50, + "seniorityLevel": "expert", + "yearsExperience": 10, + "skills": [ + "Serverless", + "GitLab", + "CI/CD", + "Docker", + "web" + ] + }, + { + "id": "aya", + "fullName": "aya", + "role": "Administrateur Système & Infrastructure Distribuée", + "availability": 30, + "seniorityLevel": "expert", + "yearsExperience": 23, + "skills": [ + "Linux", + "glusterfs", + "cephfs", + "ipfs", + "infrastructure", + "systèmes distribués", + "ThreeFold" + ] + }, + { + "id": "boris", + "fullName": "boris", + "role": "UX/UI Designer & Développeur Full Stack", + "availability": 40, + "seniorityLevel": "intermediate", + "yearsExperience": 8, + "skills": [ + "UX", + "UI", + "Figma", + "LLM", + "JavaScript", + "TypeScript", + "APIs", + "Vis.js" + ] + }, + { + "id": "elois", + "fullName": "Eloïs", + "role": "Développeur Blockchain", + "availability": 25, + "seniorityLevel": "expert", + "yearsExperience": 5, + "skills": [ + "Rust", + "blockchain", + "Substrate", + "migration" + ] + }, + { + "id": "fred", + "fullName": "Fred", + "role": "Développeur & Architecte Systèmes Décentralisés", + "availability": 40, + "seniorityLevel": "expert", + "yearsExperience": 20, + "skills": [ + "IPFS", + "Secure ScuttleButt", + "Nostr", + "TiddlyWiki", + "développement", + "ThreeFold" + ] + }, + { + "id": "hugo", + "fullName": "Hugo Trentesaux", + "role": "Financement & Gestion", + "availability": 20, + "seniorityLevel": "intermediate", + "yearsExperience": 5, + "skills": [ + "financement", + "rédaction", + "gestion" + ] + }, + { + "id": "manuTopik", + "fullName": "ManUtopiK", + "role": "Développeur Web Full Stack", + "availability": 40, + "seniorityLevel": "expert", + "yearsExperience": 12, + "skills": [ + "VueJS", + "Nuxt.js", + "JavaScript", + "TypeScript", + "CMS", + "web" + ] + }, + { + "id": "poka", + "fullName": "Poka", + "role": "Développeur Full Stack & Administrateur Système", + "availability": 50, + "seniorityLevel": "expert", + "yearsExperience": 8, + "skills": [ + "Flutter", + "Dart", + "Python", + "bash", + "ProxMox", + "infrastructure" + ] + }, + { + "id": "syoul", + "fullName": "Syoul", + "role": "Artisan Libriste & Animateur", + "availability": 30, + "seniorityLevel": "intermediate", + "yearsExperience": 6, + "skills": [ + "bidouille", + "résilience", + "domotique", + "infrastructure décentralisée" + ] + }, + { + "id": "tuxmain", + "fullName": "tuxmain", + "role": "Étudiant Math & Cryptographie", + "availability": 20, + "seniorityLevel": "beginner", + "yearsExperience": 3, + "skills": [ + "cryptographie", + "chiffrage", + "math", + "électronique" + ] + }, + { + "id": "vivien", + "fullName": "Vivien", + "role": "Développeur", + "availability": 30, + "seniorityLevel": "beginner", + "yearsExperience": 2, + "skills": [ + "Cesium", + "Godot" + ] + }, + { + "id": "yvv", + "fullName": "Yvv", + "role": "Gestion & Mobilisation", + "availability": 20, + "seniorityLevel": "senior", + "yearsExperience": 10, + "skills": [ + "gestion", + "médiathèque", + "wiki" + ] + } + ], + "generatedAt": "2025-12-06T20:48:06.056Z" +} \ No newline at end of file diff --git a/public/team.html b/public/team.html new file mode 100644 index 0000000..22f835e --- /dev/null +++ b/public/team.html @@ -0,0 +1,584 @@ + + + + + + Équipe & Technologies - Laplank + + + + + + +
+
+

👥 Équipe & Technologies

+

Visualisation des compétences et identification de l'équipe de genèse MVP

+
+ +
+ + + +
+ +
+
+
+
+ Core (Critique) +
+
+
+ Strategic +
+
+
+ Support +
+
+
+ Membres +
+
+
+
+ +
+

Matrice de Congestion - Technologies Core

+
+
+ +
+
+
Chargement des données...
+
+
+
+ + + + + diff --git a/scripts/generate-team-visualization-data.js b/scripts/generate-team-visualization-data.js new file mode 100755 index 0000000..0f5c4b7 --- /dev/null +++ b/scripts/generate-team-visualization-data.js @@ -0,0 +1,376 @@ +#!/usr/bin/env node + +/** + * Script pour générer les données de visualisation équipe/technologies + * Génère un fichier JSON pour les visualisations Cytoscape.js et ECharts + */ + +const fs = require('fs'); +const path = require('path'); + +// Extraire une valeur YAML +function extractYaml(yamlContent, key) { + const regex = new RegExp(`^${key}:\\s*["']?([^"'\n]+)["']?`, 'm'); + const match = yamlContent.match(regex); + return match ? match[1].trim() : null; +} + +// Extraire les compétences depuis le YAML +function extractSkills(yamlContent) { + const skills = []; + const lines = yamlContent.split('\n'); + let inSkillsSection = false; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + + if (line.match(/^skills:\s*$/)) { + inSkillsSection = true; + continue; + } + + if (inSkillsSection && line.match(/^\w+:/) && !line.match(/^\s+/)) { + inSkillsSection = false; + continue; + } + + if (inSkillsSection) { + const nameMatch = line.match(/^\s+-\s+name:\s*["']?([^"'\n]+)["']?/); + if (nameMatch) { + skills.push(nameMatch[1]); + } + } + } + + return skills; +} + +// Charger les technologies depuis les blips +function loadTechnologies() { + const techDir = path.join(__dirname, '../radar-business/2025-01-15'); + const technologies = []; + + if (!fs.existsSync(techDir)) { + console.warn(`⚠️ Dossier ${techDir} introuvable`); + return []; + } + + const files = fs.readdirSync(techDir).filter(f => f.endsWith('.md')); + + for (const file of files) { + const filePath = path.join(techDir, file); + const content = fs.readFileSync(filePath, 'utf-8'); + const yamlMatch = content.match(/^---\n([\s\S]*?)\n---/); + if (!yamlMatch) continue; + + const yaml = yamlMatch[1]; + + // Extraire les membres depuis la section "Compétences" + let members = []; + const compSection = content.match(/## Compétences\s*\n([\s\S]*?)(?=\n## |$)/); + if (compSection) { + const membersMatch = compSection[1].match(/Membres de l'équipe\s*:\s*([^\n]+)/); + if (membersMatch) { + members = membersMatch[1].split(',').map(m => m.trim()).filter(m => m && m !== 'Aucun'); + } + } + + const tech = { + id: file.replace('.md', ''), + title: extractYaml(yaml, 'title') || file.replace('.md', ''), + ring: extractYaml(yaml, 'ring') || 'support', + quadrant: extractYaml(yaml, 'quadrant') || 'technologies-commodite', + businessImpact: extractYaml(yaml, 'businessImpact') || 'medium', + teamCoverage: parseInt(extractYaml(yaml, 'teamCoverage') || '0'), + skillGap: extractYaml(yaml, 'skillGap') || 'medium', + competencyLevel: extractYaml(yaml, 'competencyLevel') || 'beginner', + members: members + }; + + technologies.push(tech); + } + + return technologies; +} + +// Charger les membres de l'équipe +function loadTeamMembers() { + const teamDir = path.join(__dirname, '../docs/data/team'); + const members = []; + + if (!fs.existsSync(teamDir)) { + console.warn(`⚠️ Dossier ${teamDir} introuvable`); + return []; + } + + const files = fs.readdirSync(teamDir).filter(f => f.endsWith('.md')); + + for (const file of files) { + const filePath = path.join(teamDir, file); + const content = fs.readFileSync(filePath, 'utf-8'); + const yamlMatch = content.match(/^---\n([\s\S]*?)\n---/); + if (!yamlMatch) continue; + + const yaml = yamlMatch[1]; + const member = { + id: extractYaml(yaml, 'name') || file.replace('.md', ''), + fullName: extractYaml(yaml, 'fullName') || extractYaml(yaml, 'name'), + role: extractYaml(yaml, 'role') || '', + availability: parseInt(extractYaml(yaml, 'availability') || '0'), + seniorityLevel: extractYaml(yaml, 'seniorityLevel') || 'beginner', + yearsExperience: parseInt(extractYaml(yaml, 'yearsExperience') || '0'), + skills: extractSkills(yaml) + }; + + members.push(member); + } + + return members; +} + +// Générer les données pour le graphe réseau (Cytoscape.js) +function generateNetworkData(technologies, members) { + const nodes = []; + const edges = []; + + // Nœuds technologies + technologies.forEach(tech => { + const ringColor = { + 'core': '#ff4444', + 'strategic': '#ff8800', + 'support': '#4488ff', + 'legacy': '#888888' + }[tech.ring] || '#999999'; + + nodes.push({ + data: { + id: `tech-${tech.id}`, + label: tech.title, + type: 'technology', + ring: tech.ring, + quadrant: tech.quadrant, + coverage: tech.teamCoverage, + businessImpact: tech.businessImpact, + skillGap: tech.skillGap, + color: ringColor + } + }); + }); + + // Nœuds membres + members.forEach(member => { + nodes.push({ + data: { + id: `member-${member.id}`, + label: member.fullName || member.id, + type: 'member', + availability: member.availability, + seniority: member.seniorityLevel, + role: member.role + } + }); + }); + + // Liens technologies ↔ membres + technologies.forEach(tech => { + tech.members.forEach(memberName => { + const member = members.find(m => { + const mId = m.id.toLowerCase(); + const mFullName = (m.fullName || '').toLowerCase(); + const memberNameLower = memberName.toLowerCase(); + return mId === memberNameLower || mFullName === memberNameLower; + }); + + if (member) { + // Vérifier si le membre a vraiment cette compétence + const hasSkill = member.skills.some(skill => { + const skillLower = skill.toLowerCase(); + const techTitleLower = tech.title.toLowerCase(); + return skillLower.includes(techTitleLower) || + techTitleLower.includes(skillLower) || + tech.title.toLowerCase().split(/[\s\/-]/).some(word => + skillLower.includes(word) || word.length > 3 && skillLower.includes(word) + ); + }); + + if (hasSkill || tech.members.includes(member.id) || tech.members.includes(member.fullName)) { + edges.push({ + data: { + id: `edge-${tech.id}-${member.id}`, + source: `tech-${tech.id}`, + target: `member-${member.id}`, + weight: hasSkill ? 1 : 0.5 + } + }); + } + } + }); + }); + + return { nodes, edges }; +} + +// Générer la matrice de congestion +function generateCongestionMatrix(technologies, members) { + // Filtrer technologies core uniquement + const coreTechs = technologies.filter(t => t.ring === 'core').sort((a, b) => { + // Trier par businessImpact puis par coverage + const impactOrder = { 'high': 3, 'medium': 2, 'low': 1 }; + const impactDiff = (impactOrder[b.businessImpact] || 0) - (impactOrder[a.businessImpact] || 0); + if (impactDiff !== 0) return impactDiff; + return a.teamCoverage - b.teamCoverage; // Moins de couverture = plus critique + }); + + // Filtrer membres avec disponibilité >= 50% + const availableMembers = members.filter(m => m.availability >= 50) + .sort((a, b) => b.availability - a.availability); + + const matrix = []; + + coreTechs.forEach(tech => { + const row = { + technology: tech.title, + technologyId: tech.id, + businessImpact: tech.businessImpact, + coverage: tech.teamCoverage, + skillGap: tech.skillGap, + members: [] + }; + + availableMembers.forEach(member => { + const hasSkill = tech.members.some(m => { + const mId = m.toLowerCase(); + return mId === member.id.toLowerCase() || + mId === (member.fullName || '').toLowerCase(); + }); + + row.members.push({ + member: member.id, + fullName: member.fullName, + hasSkill: hasSkill, + availability: member.availability, + seniority: member.seniorityLevel + }); + }); + + matrix.push(row); + }); + + return matrix; +} + +// Générer l'équipe de genèse MVP +function generateGenesisTeam(technologies, members) { + const coreTechs = technologies.filter(t => t.ring === 'core'); + const availableMembers = members.filter(m => m.availability >= 50); + + const genesisTeam = []; + const coveredTechs = new Set(); + const memberTechMap = new Map(); + + // Pour chaque membre, lister les technos core qu'il maîtrise + availableMembers.forEach(member => { + const memberTechs = coreTechs.filter(tech => { + return tech.members.some(m => { + const mId = m.toLowerCase(); + return mId === member.id.toLowerCase() || + mId === (member.fullName || '').toLowerCase(); + }); + }); + + if (memberTechs.length > 0) { + memberTechMap.set(member.id, { + member: member, + technologies: memberTechs, + coverage: memberTechs.length + }); + + memberTechs.forEach(t => coveredTechs.add(t.id)); + } + }); + + // Sélectionner les membres qui couvrent le plus de technos + const sortedMembers = Array.from(memberTechMap.entries()) + .sort((a, b) => b[1].coverage - a[1].coverage); + + sortedMembers.forEach(([memberId, data]) => { + genesisTeam.push({ + member: data.member.id, + fullName: data.member.fullName, + role: data.member.role, + availability: data.member.availability, + seniority: data.member.seniorityLevel, + technologies: data.technologies.map(t => ({ + id: t.id, + title: t.title, + businessImpact: t.businessImpact + })), + coverage: data.coverage + }); + }); + + // Identifier les technos non couvertes + const uncoveredTechs = coreTechs.filter(t => !coveredTechs.has(t.id)); + + return { + team: genesisTeam, + totalMembers: genesisTeam.length, + coveredTechnologies: coveredTechs.size, + totalCoreTechnologies: coreTechs.length, + uncoveredTechnologies: uncoveredTechs.map(t => ({ + id: t.id, + title: t.title, + businessImpact: t.businessImpact, + skillGap: t.skillGap, + teamCoverage: t.teamCoverage + })), + totalCapacity: genesisTeam.reduce((sum, m) => sum + m.availability, 0), + averageAvailability: genesisTeam.length > 0 + ? Math.round(genesisTeam.reduce((sum, m) => sum + m.availability, 0) / genesisTeam.length) + : 0 + }; +} + +// Main +function main() { + console.log('📊 Génération des données de visualisation équipe/technologies...\n'); + + const technologies = loadTechnologies(); + const members = loadTeamMembers(); + + console.log(`✅ ${technologies.length} technologies chargées`); + console.log(`✅ ${members.length} membres chargés`); + + const data = { + network: generateNetworkData(technologies, members), + congestionMatrix: generateCongestionMatrix(technologies, members), + genesisTeam: generateGenesisTeam(technologies, members), + technologies: technologies, + members: members, + generatedAt: new Date().toISOString() + }; + + const outputPath = path.join(__dirname, '../public/team-visualization-data.json'); + fs.writeFileSync(outputPath, JSON.stringify(data, null, 2), 'utf-8'); + + console.log(`\n✅ Données générées: ${outputPath}`); + console.log(`📊 Graphe réseau: ${data.network.nodes.length} nœuds, ${data.network.edges.length} liens`); + console.log(`🔥 Matrice congestion: ${data.congestionMatrix.length} technologies core`); + console.log(`👥 Équipe de genèse: ${data.genesisTeam.totalMembers} membres`); + console.log(` - Capacité totale: ${data.genesisTeam.totalCapacity}%`); + console.log(` - Disponibilité moyenne: ${data.genesisTeam.averageAvailability}%`); + console.log(` - Technologies couvertes: ${data.genesisTeam.coveredTechnologies}/${data.genesisTeam.totalCoreTechnologies}`); + if (data.genesisTeam.uncoveredTechnologies.length > 0) { + console.log(`⚠️ Technologies non couvertes: ${data.genesisTeam.uncoveredTechnologies.length}`); + data.genesisTeam.uncoveredTechnologies.forEach(t => { + console.log(` - ${t.title} (${t.businessImpact} impact, ${t.skillGap} gap)`); + }); + } +} + +if (require.main === module) { + main(); +} + +module.exports = { loadTechnologies, loadTeamMembers, generateNetworkData, generateCongestionMatrix, generateGenesisTeam }; +