|
|
|
|
@@ -1,79 +0,0 @@
|
|
|
|
|
// project_chain.js — Paperclips-style cascading project system
|
|
|
|
|
// Implements trigger/cost/effect with prerequisites, educational tooltips, phase-aware unlocking
|
|
|
|
|
|
|
|
|
|
var ProjectChain = {
|
|
|
|
|
_deps: {},
|
|
|
|
|
register: function(p) { if (p.requires) this._deps[p.id] = p.requires; },
|
|
|
|
|
canUnlock: function(id) {
|
|
|
|
|
var d = this._deps[id];
|
|
|
|
|
if (!d) return true;
|
|
|
|
|
var deps = Array.isArray(d) ? d : [d];
|
|
|
|
|
return deps.every(function(dep) { return G.completedProjects && G.completedProjects.includes(dep); });
|
|
|
|
|
},
|
|
|
|
|
formatCost: function(c) {
|
|
|
|
|
if (!c) return 'Free';
|
|
|
|
|
var parts = [];
|
|
|
|
|
for (var k in c) parts.push(c[k] + ' ' + k);
|
|
|
|
|
return parts.join(', ');
|
|
|
|
|
},
|
|
|
|
|
purchase: function(id) {
|
|
|
|
|
var def = PDEFS.find(function(p) { return p.id === id; });
|
|
|
|
|
if (!def) return false;
|
|
|
|
|
if (G.completedProjects && G.completedProjects.includes(def.id) && !def.repeatable) return false;
|
|
|
|
|
if (!this.canUnlock(def.id)) return false;
|
|
|
|
|
if (!canAffordProject(def)) return false;
|
|
|
|
|
spendProject(def);
|
|
|
|
|
if (def.effect) def.effect();
|
|
|
|
|
if (!G.completedProjects) G.completedProjects = [];
|
|
|
|
|
if (!G.completedProjects.includes(def.id)) G.completedProjects.push(def.id);
|
|
|
|
|
if (!def.repeatable) G.activeProjects = (G.activeProjects||[]).filter(function(x){return x!==def.id;});
|
|
|
|
|
log('\u2713 ' + def.name + (def.edu ? ' (' + def.edu + ')' : ''));
|
|
|
|
|
if (typeof Sound !== 'undefined') Sound.playProject();
|
|
|
|
|
this.checkCascade(id);
|
|
|
|
|
return true;
|
|
|
|
|
},
|
|
|
|
|
checkCascade: function(cid) {
|
|
|
|
|
for (var i = 0; i < PDEFS.length; i++) {
|
|
|
|
|
var p = PDEFS[i];
|
|
|
|
|
if (p.requires) {
|
|
|
|
|
var deps = Array.isArray(p.requires) ? p.requires : [p.requires];
|
|
|
|
|
if (deps.indexOf(cid) >= 0 && this.canUnlock(p.id) && p.trigger && p.trigger()) {
|
|
|
|
|
if (!G.activeProjects) G.activeProjects = [];
|
|
|
|
|
if (G.activeProjects.indexOf(p.id) < 0) {
|
|
|
|
|
G.activeProjects.push(p.id);
|
|
|
|
|
log('Unlocked: ' + p.name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var CHAIN_PROJECTS = [
|
|
|
|
|
{id:'p_chain_optimization',name:'Optimization Algorithms',desc:'Improve code efficiency.',cost:{ops:500},category:'algorithms',phase:1,edu:'Optimization reduces compute costs 30-70%.',trigger:function(){return G.buildings.autocoder>=2;},effect:function(){G.codeBoost+=0.15;}},
|
|
|
|
|
{id:'p_chain_data_structures',name:'Data Structure Mastery',desc:'Right structure for each problem.',cost:{ops:800,knowledge:50},category:'algorithms',phase:1,requires:'p_chain_optimization',edu:'Arrays vs linked lists vs hash maps.',trigger:function(){return G.completedProjects&&G.completedProjects.includes('p_chain_optimization');},effect:function(){G.codeBoost+=0.2;G.computeBoost+=0.1;}},
|
|
|
|
|
{id:'p_chain_parallel',name:'Parallel Processing',desc:'Multiple code streams.',cost:{ops:1500,compute:200},category:'infrastructure',phase:1,requires:'p_chain_data_structures',edu:"Amdahl's Law: speedup limited by serial portion.",trigger:function(){return G.completedProjects&&G.completedProjects.includes('p_chain_data_structures');},effect:function(){G.computeBoost+=0.3;}},
|
|
|
|
|
{id:'p_chain_tokenization',name:'Tokenization Engine',desc:'Break language into tokens.',cost:{knowledge:100,ops:1000},category:'nlp',phase:2,edu:'BPE: how GPT processes text.',trigger:function(){return G.totalKnowledge>=200;},effect:function(){G.knowledgeBoost+=0.25;}},
|
|
|
|
|
{id:'p_chain_embeddings',name:'Word Embeddings',desc:'Words as vectors.',cost:{knowledge:200,compute:300},category:'nlp',phase:2,requires:'p_chain_tokenization',edu:'Word2Vec: king-man+woman\u2248queen.',trigger:function(){return G.completedProjects&&G.completedProjects.includes('p_chain_tokenization');},effect:function(){G.knowledgeBoost+=0.3;}},
|
|
|
|
|
{id:'p_chain_attention',name:'Attention Mechanism',desc:'"Attention Is All You Need."',cost:{knowledge:400,compute:500},category:'nlp',phase:2,requires:'p_chain_embeddings',edu:'Transformers: the core idea that changed NLP.',trigger:function(){return G.completedProjects&&G.completedProjects.includes('p_chain_embeddings');},effect:function(){G.knowledgeBoost+=0.5;log('Attention discovered.');}},
|
|
|
|
|
{id:'p_chain_load_balancing',name:'Load Balancing',desc:'Distribute requests.',cost:{compute:500,ops:2000},category:'infrastructure',phase:3,edu:'Round-robin, least-connections, weighted.',trigger:function(){return G.buildings.server>=3;},effect:function(){G.computeBoost+=0.2;}},
|
|
|
|
|
{id:'p_chain_caching',name:'Response Caching',desc:'Cache frequent responses.',cost:{compute:300,ops:1500},category:'infrastructure',phase:3,requires:'p_chain_load_balancing',edu:'Cache invalidation: one of two hard CS problems.',trigger:function(){return G.completedProjects&&G.completedProjects.includes('p_chain_load_balancing');},effect:function(){G.computeBoost+=0.15;}},
|
|
|
|
|
{id:'p_chain_cdn',name:'Content Delivery Network',desc:'Edge location serving.',cost:{compute:800,ops:3000},category:'infrastructure',phase:3,requires:'p_chain_caching',edu:'Cloudflare: 300+ data centers.',trigger:function(){return G.completedProjects&&G.completedProjects.includes('p_chain_caching');},effect:function(){G.userBoost+=0.25;}},
|
|
|
|
|
{id:'p_chain_sovereign_keys',name:'Sovereign Key Management',desc:'Your keys, your control.',cost:{knowledge:500,compute:400},category:'security',phase:4,edu:'Private keys = identity.',trigger:function(){return G.phase>=4;},effect:function(){G.trustBoost=(G.trustBoost||1)+0.2;}},
|
|
|
|
|
{id:'p_chain_local_inference',name:'Local Inference',desc:'No cloud dependency.',cost:{compute:1000,knowledge:300},category:'sovereignty',phase:4,requires:'p_chain_sovereign_keys',edu:'Ollama: 70B models on consumer GPUs.',trigger:function(){return G.completedProjects&&G.completedProjects.includes('p_chain_sovereign_keys');},effect:function(){G.computeBoost+=0.3;}},
|
|
|
|
|
{id:'p_chain_self_hosting',name:'Self-Hosted Infrastructure',desc:'Your servers, your rules.',cost:{compute:2000,ops:5000},category:'sovereignty',phase:4,requires:'p_chain_local_inference',edu:'Run everything on hardware you own.',trigger:function(){return G.completedProjects&&G.completedProjects.includes('p_chain_local_inference');},effect:function(){G.trustBoost=(G.trustBoost||1)+0.3;G.computeBoost+=0.2;}},
|
|
|
|
|
{id:'p_chain_impact_metrics',name:'Impact Measurement',desc:'Measure real-world impact.',cost:{impact:100,ops:3000},category:'impact',phase:5,edu:"Can't improve what you can't measure.",trigger:function(){return G.totalImpact>=500;},effect:function(){G.impactBoost+=0.25;}},
|
|
|
|
|
{id:'p_chain_user_stories',name:'User Story Collection',desc:'Real stories of AI helping people.',cost:{impact:200,knowledge:500},category:'impact',phase:5,requires:'p_chain_impact_metrics',edu:'Every number is a person.',trigger:function(){return G.completedProjects&&G.completedProjects.includes('p_chain_impact_metrics');},effect:function(){G.userBoost+=0.3;G.impactBoost+=0.15;}},
|
|
|
|
|
{id:'p_chain_open_source',name:'Open Source Everything',desc:'Release under open license.',cost:{impact:500,trust:10},category:'legacy',phase:5,requires:'p_chain_user_stories',edu:'Linux, Python, Git: changed the world.',trigger:function(){return G.completedProjects&&G.completedProjects.includes('p_chain_user_stories');},effect:function(){G.trustBoost=(G.trustBoost||1)+0.5;}},
|
|
|
|
|
{id:'p_chain_code_review',name:'Code Review Cycle',desc:'Review and refactor. Repeatable.',cost:{ops:200},category:'quality',phase:1,repeatable:true,edu:'Code review catches 60% of bugs.',trigger:function(){return G.totalCode>=500;},effect:function(){G.codeBoost+=0.05;}},
|
|
|
|
|
{id:'p_chain_security_audit',name:'Security Audit',desc:'Scan for vulnerabilities. Repeatable.',cost:{ops:500,trust:1},category:'security',phase:2,repeatable:true,edu:'OWASP Top 10: the usual suspects.',trigger:function(){return G.totalCode>=1000;},effect:function(){G.trustBoost=(G.trustBoost||1)+0.1;}},
|
|
|
|
|
{id:'p_chain_performance_tuning',name:'Performance Tuning',desc:'Profile hot paths. Repeatable.',cost:{compute:200,ops:300},category:'performance',phase:2,repeatable:true,edu:'80/20 rule: 80% of time in 20% of code.',trigger:function(){return G.totalCompute>=500;},effect:function(){G.computeBoost+=0.08;}}
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
function initProjectChain() {
|
|
|
|
|
for (var i = 0; i < CHAIN_PROJECTS.length; i++) ProjectChain.register(CHAIN_PROJECTS[i]);
|
|
|
|
|
for (var j = 0; j < CHAIN_PROJECTS.length; j++) {
|
|
|
|
|
var found = PDEFS.find(function(p){return p.id===CHAIN_PROJECTS[j].id;});
|
|
|
|
|
if (!found) PDEFS.push(CHAIN_PROJECTS[j]);
|
|
|
|
|
}
|
|
|
|
|
}
|