pre-mortem 0.1.5 → 0.1.7

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.
Binary file
@@ -2,7 +2,7 @@ var m = Object.defineProperty;
2
2
  var b = (r, t, e) => t in r ? m(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;
3
3
  var l = (r, t, e) => b(r, typeof t != "symbol" ? t + "" : t, e);
4
4
  import c from "matter-js";
5
- var u = /* @__PURE__ */ ((r) => (r.BOOTSTRAP = "bootstrap", r.VC = "vc", r.SLACKER = "slacker", r.CONTROL_FREAK = "control_freak", r.PRIMA_DONNA = "prima_donna", r.QUIET_QUITTER = "quiet_quitter", r.SLACK_SPAMMER = "slack_spammer", r))(u || {});
5
+ var g = /* @__PURE__ */ ((r) => (r.BOOTSTRAP = "bootstrap", r.VC = "vc", r.SLACKER = "slacker", r.CONTROL_FREAK = "control_freak", r.PRIMA_DONNA = "prima_donna", r.QUIET_QUITTER = "quiet_quitter", r.SLACK_SPAMMER = "slack_spammer", r))(g || {});
6
6
  const p = {
7
7
  bootstrap: {
8
8
  w: 132,
@@ -168,30 +168,29 @@ const p = {
168
168
  label: s
169
169
  };
170
170
  if (e === "vc") {
171
- const n = i.w, d = i.h, g = Math.random() * 15, h = Math.random() * 15, a = (Math.random() - 0.5) * 20, f = [
172
- { x: 0 + a, y: g },
171
+ const n = i.w, u = i.h, h = Math.random() * 15, d = Math.random() * 15, a = (Math.random() - 0.5) * 20, f = [
172
+ { x: 0 + a, y: h },
173
173
  // TL
174
- { x: n + a, y: h },
174
+ { x: n + a, y: d },
175
175
  // TR
176
- { x: n, y: d },
176
+ { x: n, y: u },
177
177
  // BR
178
- { x: 0, y: d }
178
+ { x: 0, y: u }
179
179
  // BL
180
180
  ];
181
181
  return c.Bodies.fromVertices(r, t, [f], o);
182
182
  } else if (e === "slacker" || e === "control_freak" || e === "prima_donna" || e === "quiet_quitter" || e === "slack_spammer") {
183
- const d = {
183
+ const n = "https://raw.githubusercontent.com/Booby-Boobs/pre-mortem/main/public/", u = {
184
+ slacker: `${n}slacker.png`,
185
+ control_freak: `${n}control-freak.png`,
186
+ prima_donna: `${n}prima-donna.png`,
187
+ quiet_quitter: `${n}quet-quitter.png`,
188
+ slack_spammer: `${n}slack-spammer.png`
189
+ }, h = {
184
190
  ...o,
185
191
  render: {
186
192
  sprite: {
187
- texture: {
188
- slacker: "./slacker.png",
189
- control_freak: "./control-freak.png",
190
- prima_donna: "./prima-donna.png",
191
- quiet_quitter: "./quet-quitter.png",
192
- // User typo kept
193
- slack_spammer: "./slack-spammer.png"
194
- }[e],
193
+ texture: u[e],
195
194
  xScale: i.w / 512 * 2,
196
195
  // Approximate
197
196
  yScale: i.h / 512 * 2
@@ -200,7 +199,7 @@ const p = {
200
199
  strokeStyle: "#ffffff"
201
200
  }
202
201
  };
203
- return e === "quiet_quitter" ? c.Bodies.circle(r, t, i.w / 2, d) : e === "control_freak" ? c.Bodies.trapezoid(r, t, i.w, i.h, 0.5, d) : e === "prima_donna" ? c.Bodies.polygon(r, t, 5, i.w / 2, d) : e === "slack_spammer" ? c.Bodies.polygon(r, t, 6, i.w / 2, d) : c.Bodies.rectangle(r, t, i.w, i.h, d);
202
+ return e === "quiet_quitter" ? c.Bodies.circle(r, t, i.w / 2, h) : e === "control_freak" ? c.Bodies.trapezoid(r, t, i.w, i.h, 0.5, h) : e === "prima_donna" ? c.Bodies.polygon(r, t, 5, i.w / 2, h) : e === "slack_spammer" ? c.Bodies.polygon(r, t, 6, i.w / 2, h) : c.Bodies.rectangle(r, t, i.w, i.h, h);
204
203
  } else
205
204
  return c.Bodies.rectangle(r, t, i.w, i.h, o);
206
205
  };
@@ -358,9 +357,9 @@ class w {
358
357
  }
359
358
  initRenderLoop() {
360
359
  c.Events.on(this.render, "afterRender", () => {
361
- const t = this.render.context, e = this.width / 2, i = 400, s = 700, o = 100, n = { x: e - i / 2, y: o, w: i, h: this.height - o }, d = { x: e - s / 2, y: o - 50, w: s, h: this.height - o + 100 };
360
+ const t = this.render.context, e = this.width / 2, i = 400, s = 700, o = 100, n = { x: e - i / 2, y: o, w: i, h: this.height - o }, u = { x: e - s / 2, y: o - 50, w: s, h: this.height - o + 100 };
362
361
  if (t.beginPath(), t.setLineDash([10, 10]), t.lineWidth = 2, t.strokeStyle = "rgba(255, 255, 255, 0.3)", t.strokeRect(n.x, n.y, n.w, n.h), t.font = '10px "Inter", sans-serif', t.fillStyle = "rgba(255, 255, 255, 0.3)", t.textAlign = "center", t.fillText("ACCURATE VALUATION ZONE", e, n.y - 15), !this.currentQuote) {
363
- const h = [
362
+ const d = [
364
363
  { text: `WE ARE A
365
364
  FAMILY`, author: "- CEO" },
366
365
  { text: `CHANGE THE
@@ -380,15 +379,15 @@ GROWTH`, author: "- Investor" },
380
379
  { text: `PIVOT
381
380
  TO AI`, author: "- Board" }
382
381
  ];
383
- this.currentQuote = h[Math.floor(Math.random() * h.length)];
382
+ this.currentQuote = d[Math.floor(Math.random() * d.length)];
384
383
  }
385
384
  t.save(), t.translate(e, n.y + n.h / 3), t.rotate(-Math.PI / 12), t.textAlign = "center", t.textBaseline = "middle", t.font = '900 48px "Inter", sans-serif', t.fillStyle = "rgba(255, 255, 255, 0.05)";
386
- const g = this.currentQuote.text.split(`
385
+ const h = this.currentQuote.text.split(`
387
386
  `);
388
- g.forEach((h, a) => t.fillText(h, 0, a * 50)), t.font = 'italic 700 24px "Inter", sans-serif', t.fillStyle = "rgba(255, 255, 255, 0.04)", t.fillText(this.currentQuote.author, 0, g.length * 50 + 10), t.restore(), t.beginPath(), t.setLineDash([]), t.lineWidth = 1, t.strokeStyle = "rgba(255, 50, 50, 0.2)", t.strokeRect(d.x, d.y, d.w, d.h), t.font = 'bold 13px "Inter", sans-serif', t.textAlign = "center", t.textBaseline = "middle", t.fillStyle = "#FFFFFF", this.engine.world.bodies.forEach((h) => {
389
- if (!h.label || h.label.includes("Body") || h.isStatic) return;
390
- const a = h.gameData, f = a && a.vested;
391
- t.save(), t.translate(h.position.x, h.position.y), t.rotate(h.angle), f ? (t.shadowColor = "#00ff7f", t.shadowBlur = 10, t.fillStyle = "#00ff7f", t.fillText(h.label + " ✓", 0, 0)) : (t.shadowColor = "black", t.shadowBlur = 4, t.fillStyle = "#FFFFFF", t.fillText(h.label, 0, 0)), t.restore();
387
+ h.forEach((d, a) => t.fillText(d, 0, a * 50)), t.font = 'italic 700 24px "Inter", sans-serif', t.fillStyle = "rgba(255, 255, 255, 0.04)", t.fillText(this.currentQuote.author, 0, h.length * 50 + 10), t.restore(), t.beginPath(), t.setLineDash([]), t.lineWidth = 1, t.strokeStyle = "rgba(255, 50, 50, 0.2)", t.strokeRect(u.x, u.y, u.w, u.h), t.font = 'bold 13px "Inter", sans-serif', t.textAlign = "center", t.textBaseline = "middle", t.fillStyle = "#FFFFFF", this.engine.world.bodies.forEach((d) => {
388
+ if (!d.label || d.label.includes("Body") || d.isStatic) return;
389
+ const a = d.gameData, f = a && a.vested;
390
+ t.save(), t.translate(d.position.x, d.position.y), t.rotate(d.angle), f ? (t.shadowColor = "#00ff7f", t.shadowBlur = 10, t.fillStyle = "#00ff7f", t.fillText(d.label + " ✓", 0, 0)) : (t.shadowColor = "black", t.shadowBlur = 4, t.fillStyle = "#FFFFFF", t.fillText(d.label, 0, 0)), t.restore();
392
391
  });
393
392
  });
394
393
  }
@@ -403,13 +402,13 @@ TO AI`, author: "- Board" }
403
402
  const n = o.gameData;
404
403
  if (Math.abs(o.position.x - e) > s / 2 || o.position.y > this.height + 50) {
405
404
  c.Composite.remove(this.engine.world, o);
406
- const g = ["VC Scolding!", "Server Outage!", "GDPR Violation!", "TechCrunch Hit Piece!", "IP Lawsuit!"];
407
- this.gameState.penalty(5e4, g[Math.floor(Math.random() * g.length)]);
405
+ const h = ["VC Scolding!", "Server Outage!", "GDPR Violation!", "TechCrunch Hit Piece!", "IP Lawsuit!"];
406
+ this.gameState.penalty(5e4, h[Math.floor(Math.random() * h.length)]);
408
407
  return;
409
408
  }
410
409
  if (n && !n.vested) {
411
- const g = o.speed < 0.15 && Math.abs(o.angularVelocity) < 0.05, h = Math.abs(o.position.x - e) < i / 2;
412
- g && h ? (n.vestTimer += this.runner.delta, n.vestTimer > 1e3 && (n.vested = !0, this.gameState.addValuation(n.value))) : n.vestTimer = 0;
410
+ const h = o.speed < 0.15 && Math.abs(o.angularVelocity) < 0.05, d = Math.abs(o.position.x - e) < i / 2;
411
+ h && d ? (n.vestTimer += this.runner.delta, n.vestTimer > 1e3 && (n.vested = !0, this.gameState.addValuation(n.value))) : n.vestTimer = 0;
413
412
  }
414
413
  });
415
414
  });
@@ -433,9 +432,9 @@ TO AI`, author: "- Board" }
433
432
  break;
434
433
  case 2:
435
434
  (s = this.onCrisis) == null || s.call(this, "LEGACY DEPRECATION", "CTO: 'Deprecating v1 API!' (Ghost Blocks)");
436
- const d = this.engine.world.bodies.filter((a) => !a.isStatic);
437
- if (d.length > 3) {
438
- const a = d[Math.floor(Math.random() * d.length)];
435
+ const u = this.engine.world.bodies.filter((a) => !a.isStatic);
436
+ if (u.length > 3) {
437
+ const a = u[Math.floor(Math.random() * u.length)];
439
438
  a.isSensor = !0, setTimeout(() => {
440
439
  a.isSensor = !1;
441
440
  }, 4e3);
@@ -448,11 +447,11 @@ TO AI`, author: "- Board" }
448
447
  break;
449
448
  case 4:
450
449
  (n = this.onCrisis) == null || n.call(this, "VIRAL SPIKE", "DevOps: 'Traffic Spike!' (Earthquake)");
451
- let g = 0;
452
- const h = setInterval(() => {
450
+ let h = 0;
451
+ const d = setInterval(() => {
453
452
  this.engine.world.bodies.forEach((a) => {
454
453
  a.isStatic || c.Body.applyForce(a, a.position, { x: (Math.random() - 0.5) * 0.05, y: (Math.random() - 0.5) * 0.05 });
455
- }), ++g > 20 && clearInterval(h);
454
+ }), ++h > 20 && clearInterval(d);
456
455
  }, 100);
457
456
  break;
458
457
  }
@@ -463,15 +462,15 @@ TO AI`, author: "- Board" }
463
462
  spawnBlock(t) {
464
463
  if (!this.gameState.isPlaying()) return;
465
464
  if (Math.random() < 1 / 15) {
466
- const o = [u.SLACKER, u.CONTROL_FREAK, u.PRIMA_DONNA, u.QUIET_QUITTER, u.SLACK_SPAMMER];
465
+ const o = [g.SLACKER, g.CONTROL_FREAK, g.PRIMA_DONNA, g.QUIET_QUITTER, g.SLACK_SPAMMER];
467
466
  t = o[Math.floor(Math.random() * o.length)];
468
467
  }
469
- t === u.BOOTSTRAP ? this.gameState.spendMoney(5e3) : t === u.VC && this.gameState.addMoney(75e3);
468
+ t === g.BOOTSTRAP ? this.gameState.spendMoney(5e3) : t === g.VC && this.gameState.addMoney(75e3);
470
469
  const e = this.width / 2 + (Math.random() - 0.5) * 40, i = y(e, S, t);
471
470
  let s = this.spawnVertical ? 90 * (Math.PI / 180) : 0;
472
- t === u.VC && (s += (Math.random() - 0.5) * (30 * (Math.PI / 180))), c.Body.setAngle(i, s), i.gameData = {
471
+ t === g.VC && (s += (Math.random() - 0.5) * (30 * (Math.PI / 180))), c.Body.setAngle(i, s), i.gameData = {
473
472
  type: t,
474
- value: t === u.VC ? 5e7 : t === u.BOOTSTRAP ? 5e6 : 0,
473
+ value: t === g.VC ? 5e7 : t === g.BOOTSTRAP ? 5e6 : 0,
475
474
  vested: !1,
476
475
  vestTimer: 0
477
476
  }, c.Composite.add(this.engine.world, i);
@@ -694,10 +693,10 @@ class k {
694
693
  t.className = "uj-controls";
695
694
  const e = document.createElement("button");
696
695
  e.className = "uj-btn uj-btn-solid", e.innerText = `Build Solid
697
- (Costs $5k)`, e.onclick = () => this.options.onSpawn(u.BOOTSTRAP);
696
+ (Costs $5k)`, e.onclick = () => this.options.onSpawn(g.BOOTSTRAP);
698
697
  const i = document.createElement("button");
699
698
  i.className = "uj-btn uj-btn-hype", i.innerText = `Hype Up
700
- (Grants $75k)`, i.onclick = () => this.options.onSpawn(u.VC), t.appendChild(e), t.appendChild(i), this.container.appendChild(t);
699
+ (Grants $75k)`, i.onclick = () => this.options.onSpawn(g.VC), t.appendChild(e), t.appendChild(i), this.container.appendChild(t);
701
700
  }
702
701
  createSystemButtons() {
703
702
  const t = document.createElement("div");
@@ -864,10 +863,10 @@ class k {
864
863
  populateGlossaryLists() {
865
864
  var i, s;
866
865
  const t = document.getElementById("uj-solid-list"), e = document.getElementById("uj-hype-list");
867
- t && e && ((i = p[u.BOOTSTRAP].possibleLabels) == null || i.forEach((o) => {
866
+ t && e && ((i = p[g.BOOTSTRAP].possibleLabels) == null || i.forEach((o) => {
868
867
  const n = document.createElement("li");
869
868
  n.textContent = o, t.appendChild(n);
870
- }), (s = p[u.VC].possibleLabels) == null || s.forEach((o) => {
869
+ }), (s = p[g.VC].possibleLabels) == null || s.forEach((o) => {
871
870
  const n = document.createElement("li");
872
871
  n.textContent = o, e.appendChild(n);
873
872
  }));
@@ -885,7 +884,7 @@ class k {
885
884
  currency: "USD",
886
885
  notation: "compact",
887
886
  maximumFractionDigits: 1
888
- }), o = t.isBankrupt() ? "uj-stat-value danger" : "uj-stat-value", n = t.getNextStageThreshold(), d = n > 0 ? `<small style="font-size:12px; opacity:0.7">Next: ${i.format(n)}</small>` : "";
887
+ }), o = t.isBankrupt() ? "uj-stat-value danger" : "uj-stat-value", n = t.getNextStageThreshold(), u = n > 0 ? `<small style="font-size:12px; opacity:0.7">Next: ${i.format(n)}</small>` : "";
889
888
  this.hudElement.innerHTML = `
890
889
  <div class="uj-stat-label">Stage</div>
891
890
  <div class="uj-stat-value">${t.stage}</div>
@@ -893,7 +892,7 @@ class k {
893
892
  <div class="uj-stat-label">Valuation</div>
894
893
  <div class="uj-stat-value" style="color: #00ff7f">
895
894
  ${e.format(t.valuation)}<br>
896
- ${d}
895
+ ${u}
897
896
  </div>
898
897
 
899
898
  <div class="uj-stat-label">Runway</div>
@@ -981,7 +980,7 @@ class k {
981
980
  }, 4e3);
982
981
  }
983
982
  }
984
- class T {
983
+ class R {
985
984
  constructor(t, e = {}) {
986
985
  l(this, "game");
987
986
  l(this, "ui");
@@ -999,7 +998,7 @@ class T {
999
998
  }
1000
999
  }
1001
1000
  export {
1002
- T as PreMortem,
1001
+ R as PreMortem,
1003
1002
  w as PreMortemGame,
1004
1003
  k as UIManager
1005
1004
  };
@@ -1,4 +1,4 @@
1
- (function(g,n){typeof exports=="object"&&typeof module<"u"?n(exports,require("matter-js")):typeof define=="function"&&define.amd?define(["exports","matter-js"],n):(g=typeof globalThis<"u"?globalThis:g||self,n(g.PreMortem={},g.Matter))})(this,function(g,n){"use strict";var E=Object.defineProperty;var C=(g,n,d)=>n in g?E(g,n,{enumerable:!0,configurable:!0,writable:!0,value:d}):g[n]=d;var l=(g,n,d)=>C(g,typeof n!="symbol"?n+"":n,d);var d=(c=>(c.BOOTSTRAP="bootstrap",c.VC="vc",c.SLACKER="slacker",c.CONTROL_FREAK="control_freak",c.PRIMA_DONNA="prima_donna",c.QUIET_QUITTER="quiet_quitter",c.SLACK_SPAMMER="slack_spammer",c))(d||{});const f={bootstrap:{w:132,h:44,color:"#555555",density:.005,friction:.8,restitution:0,label:"Refactoring",possibleLabels:["Refactoring","Unit Tests","Bug Fixes","User Support","Documentation","Security Audit","Compliance","Cleanup","Optimization","CI/CD Pipeline","Code Review","DB Tuning","API Design","Accessibility","Localization","Error Logs","Backups","Legacy Code","Hiring","Customer Love","Bossware","YAML Hell","DNS Propagation","Regex","npm audit","GDPR / SOC2","Migration","Certificate Expiry","On-Call","Technical Debt","Works on my machine","Yak Shaving"]},vc:{w:120,h:40,color:"#FF00FF",density:5e-4,friction:.3,restitution:.6,label:"AI Blockchain",possibleLabels:["GenAI","Blockchain","Web3","Metaverse","NFTs","Viral Growth","Pivot","Synergy","Disruption","Thought Leader","Influencers","Hyper-Scale","Quantum","Big Data","Growth Hack","Paradigm Shift","10x Engineer","Visionary","Series B Pitch","Exit Strategy","Vibe Coding","Founder Mode","Prompt Engineering","AGI","AI Wrapper","Unlimited PTO","Radical Candor","Community Led","Pre-Revenue","Fractional CxO"]},slacker:{w:64,h:64,color:"#FFFFFF",density:.01,friction:1,restitution:.1,label:"The Slacker",possibleLabels:["The Slacker"]},control_freak:{w:64,h:64,color:"#FF0000",density:.012,friction:.5,restitution:.2,label:"Control Freak",possibleLabels:["Control Freak"]},prima_donna:{w:56,h:56,color:"#FFFF00",density:.008,friction:.1,restitution:1.2,label:"Prima Donna",possibleLabels:["Prima Donna"]},quiet_quitter:{w:48,h:48,color:"#00FFFF",density:.005,friction:.01,restitution:.9,label:"Quiet Quitter",possibleLabels:["Quiet Quitter"]},slack_spammer:{w:60,h:60,color:"#00FF00",density:.01,friction:.4,restitution:.4,label:"Slack Spammer",possibleLabels:["Slack Spammer"]}},y=c=>{const t=f[c].possibleLabels||[];return t[Math.floor(Math.random()*t.length)]},v=(c,t,e)=>{const i=f[e],s=y(e),a={density:i.density,friction:i.friction,restitution:i.restitution,render:{fillStyle:i.color,strokeStyle:"#000",lineWidth:2},label:s};if(e==="vc"){const o=i.w,h=i.h,p=Math.random()*15,u=Math.random()*15,r=(Math.random()-.5)*20,m=[{x:0+r,y:p},{x:o+r,y:u},{x:o,y:h},{x:0,y:h}];return n.Bodies.fromVertices(c,t,[m],a)}else if(e==="slacker"||e==="control_freak"||e==="prima_donna"||e==="quiet_quitter"||e==="slack_spammer"){const h={...a,render:{sprite:{texture:{slacker:"./slacker.png",control_freak:"./control-freak.png",prima_donna:"./prima-donna.png",quiet_quitter:"./quet-quitter.png",slack_spammer:"./slack-spammer.png"}[e],xScale:i.w/512*2,yScale:i.h/512*2},lineWidth:3,strokeStyle:"#ffffff"}};return e==="quiet_quitter"?n.Bodies.circle(c,t,i.w/2,h):e==="control_freak"?n.Bodies.trapezoid(c,t,i.w,i.h,.5,h):e==="prima_donna"?n.Bodies.polygon(c,t,5,i.w/2,h):e==="slack_spammer"?n.Bodies.polygon(c,t,6,i.w/2,h):n.Bodies.rectangle(c,t,i.w,i.h,h)}else return n.Bodies.rectangle(c,t,i.w,i.h,a)};class w{constructor(t){l(this,"runway");l(this,"valuation",0);l(this,"stage");l(this,"status","playing");l(this,"lastPenaltyReason","");l(this,"config");l(this,"currentStageIndex",0);l(this,"listeners",[]);if(this.config=t,this.runway=t.initialRunway,!this.config.stages||this.config.stages.length===0)throw new Error("Game must have at least one stage defined.");this.config.stages.sort((e,i)=>e.threshold-i.threshold),this.currentStageIndex=0,this.stage=this.config.stages[0].name,this.checkStage()}setPaused(t){t?this.status==="playing"&&(this.status="paused"):this.status==="paused"&&(this.status="playing"),this.notify()}togglePause(){this.setPaused(this.status==="playing")}tick(t){if(this.status!=="playing")return;const e=Math.min(t,.1),i=this.getDynamicBurnRate();this.runway-=i*e,this.runway<=0&&(this.runway=0,this.status="bankrupt");const s=this.config.stages[this.config.stages.length-1];this.valuation>=s.threshold&&this.status==="playing"&&(this.status="exited"),this.checkStage(),this.notify()}getDynamicBurnRate(){return this.config.stages[this.currentStageIndex].burnRate}addValuation(t){this.valuation+=t,this.checkStage(),this.notify()}spendMoney(t){this.runway-=t,this.notify()}addMoney(t){this.runway+=t,this.notify()}setCollapsed(){this.status==="playing"&&(this.status="collapsed",this.notify())}getNextStageThreshold(){return this.currentStageIndex<this.config.stages.length-1?this.config.stages[this.currentStageIndex+1].threshold:this.config.stages[this.config.stages.length-1].threshold}penalty(t,e){this.runway-=t,this.lastPenaltyReason=e,this.runway<0&&(this.runway=0,this.status="bankrupt"),this.notify("penalty")}checkStage(){let t=0;for(let e=0;e<this.config.stages.length&&this.valuation>=this.config.stages[e].threshold;e++)t=e;if(t!==this.currentStageIndex){if(t>this.currentStageIndex){const e=this.config.stages[t].fundingBonus||0;e>0&&(this.addMoney(e),this.notify("funding:"+e))}this.currentStageIndex=t,this.stage=this.config.stages[t].name}}subscribe(t){this.listeners.push(t)}notify(t){this.listeners.forEach(e=>e(t))}isPlaying(){return this.status==="playing"}isBankrupt(){return this.status==="bankrupt"}}class b{constructor(t,e={}){l(this,"engine");l(this,"render");l(this,"runner");l(this,"container");l(this,"width");l(this,"height");l(this,"mouseConstraint");l(this,"currentQuote",null);l(this,"chaosTimer",1e4);l(this,"chaosInterval",9e4);l(this,"onCrisis");l(this,"gameState");l(this,"spawnVertical",!1);this.container=t,this.width=e.width||t.clientWidth||800,this.height=e.height||t.clientHeight||600,this.onCrisis=e.onCrisis,this.chaosInterval=e.chaosInterval||9e4,this.chaosTimer=e.chaosInterval?e.chaosInterval:1e4;const i=[{name:"Seed Round",threshold:0,burnRate:2e3},{name:"Series A",threshold:1e8,burnRate:1e4,fundingBonus:25e4},{name:"Series B",threshold:25e7,burnRate:25e3,fundingBonus:5e5},{name:"Series C",threshold:5e8,burnRate:5e4,fundingBonus:1e6},{name:"Series D",threshold:7e8,burnRate:75e3,fundingBonus:2e6},{name:"Series E",threshold:85e7,burnRate:1e5,fundingBonus:5e6},{name:"Unicorn Status",threshold:1e9,burnRate:15e4,fundingBonus:1e7}];this.gameState=new w({initialRunway:e.initialRunway||2e5,stages:e.stages||i}),this.engine=n.Engine.create(),this.render=n.Render.create({element:this.container,engine:this.engine,options:{width:this.width,height:this.height,wireframes:!1,background:"#1a1a1a"}}),this.runner=n.Runner.create(),this.initWorld(),this.initMouse(),this.initRenderLoop(),this.initGameLoop(),this.initControls(),this.gameState.subscribe(()=>{this.gameState.status==="paused"?this.runner.enabled=!1:this.gameState.status==="playing"&&(this.runner.enabled=!0)})}initControls(){window.addEventListener("keydown",t=>{(t.key==="r"||t.key==="R")&&this.gameState.isPlaying()&&this.rotateHeldBody()})}rotateHeldBody(){const t=this.mouseConstraint.body;t&&n.Body.rotate(t,45*(Math.PI/180))}initWorld(){const{width:t,height:e}=this,i=60,s=n.Bodies.rectangle(t/2,e-i/2,t,i,{isStatic:!0,render:{fillStyle:"#333"}});n.Composite.add(this.engine.world,[s])}initMouse(){const t=n.Mouse.create(this.render.canvas);this.mouseConstraint=n.MouseConstraint.create(this.engine,{mouse:t,constraint:{stiffness:.2,render:{visible:!1}}}),n.Composite.add(this.engine.world,this.mouseConstraint),this.render.mouse=t}start(){n.Render.run(this.render),n.Runner.run(this.runner,this.engine)}stop(){n.Render.stop(this.render),n.Runner.stop(this.runner)}initRenderLoop(){n.Events.on(this.render,"afterRender",()=>{const t=this.render.context,e=this.width/2,i=400,s=700,a=100,o={x:e-i/2,y:a,w:i,h:this.height-a},h={x:e-s/2,y:a-50,w:s,h:this.height-a+100};if(t.beginPath(),t.setLineDash([10,10]),t.lineWidth=2,t.strokeStyle="rgba(255, 255, 255, 0.3)",t.strokeRect(o.x,o.y,o.w,o.h),t.font='10px "Inter", sans-serif',t.fillStyle="rgba(255, 255, 255, 0.3)",t.textAlign="center",t.fillText("ACCURATE VALUATION ZONE",e,o.y-15),!this.currentQuote){const u=[{text:`WE ARE A
1
+ (function(p,o){typeof exports=="object"&&typeof module<"u"?o(exports,require("matter-js")):typeof define=="function"&&define.amd?define(["exports","matter-js"],o):(p=typeof globalThis<"u"?globalThis:p||self,o(p.PreMortem={},p.Matter))})(this,function(p,o){"use strict";var E=Object.defineProperty;var C=(p,o,d)=>o in p?E(p,o,{enumerable:!0,configurable:!0,writable:!0,value:d}):p[o]=d;var l=(p,o,d)=>C(p,typeof o!="symbol"?o+"":o,d);var d=(c=>(c.BOOTSTRAP="bootstrap",c.VC="vc",c.SLACKER="slacker",c.CONTROL_FREAK="control_freak",c.PRIMA_DONNA="prima_donna",c.QUIET_QUITTER="quiet_quitter",c.SLACK_SPAMMER="slack_spammer",c))(d||{});const f={bootstrap:{w:132,h:44,color:"#555555",density:.005,friction:.8,restitution:0,label:"Refactoring",possibleLabels:["Refactoring","Unit Tests","Bug Fixes","User Support","Documentation","Security Audit","Compliance","Cleanup","Optimization","CI/CD Pipeline","Code Review","DB Tuning","API Design","Accessibility","Localization","Error Logs","Backups","Legacy Code","Hiring","Customer Love","Bossware","YAML Hell","DNS Propagation","Regex","npm audit","GDPR / SOC2","Migration","Certificate Expiry","On-Call","Technical Debt","Works on my machine","Yak Shaving"]},vc:{w:120,h:40,color:"#FF00FF",density:5e-4,friction:.3,restitution:.6,label:"AI Blockchain",possibleLabels:["GenAI","Blockchain","Web3","Metaverse","NFTs","Viral Growth","Pivot","Synergy","Disruption","Thought Leader","Influencers","Hyper-Scale","Quantum","Big Data","Growth Hack","Paradigm Shift","10x Engineer","Visionary","Series B Pitch","Exit Strategy","Vibe Coding","Founder Mode","Prompt Engineering","AGI","AI Wrapper","Unlimited PTO","Radical Candor","Community Led","Pre-Revenue","Fractional CxO"]},slacker:{w:64,h:64,color:"#FFFFFF",density:.01,friction:1,restitution:.1,label:"The Slacker",possibleLabels:["The Slacker"]},control_freak:{w:64,h:64,color:"#FF0000",density:.012,friction:.5,restitution:.2,label:"Control Freak",possibleLabels:["Control Freak"]},prima_donna:{w:56,h:56,color:"#FFFF00",density:.008,friction:.1,restitution:1.2,label:"Prima Donna",possibleLabels:["Prima Donna"]},quiet_quitter:{w:48,h:48,color:"#00FFFF",density:.005,friction:.01,restitution:.9,label:"Quiet Quitter",possibleLabels:["Quiet Quitter"]},slack_spammer:{w:60,h:60,color:"#00FF00",density:.01,friction:.4,restitution:.4,label:"Slack Spammer",possibleLabels:["Slack Spammer"]}},y=c=>{const t=f[c].possibleLabels||[];return t[Math.floor(Math.random()*t.length)]},v=(c,t,e)=>{const i=f[e],s=y(e),a={density:i.density,friction:i.friction,restitution:i.restitution,render:{fillStyle:i.color,strokeStyle:"#000",lineWidth:2},label:s};if(e==="vc"){const n=i.w,g=i.h,u=Math.random()*15,h=Math.random()*15,r=(Math.random()-.5)*20,m=[{x:0+r,y:u},{x:n+r,y:h},{x:n,y:g},{x:0,y:g}];return o.Bodies.fromVertices(c,t,[m],a)}else if(e==="slacker"||e==="control_freak"||e==="prima_donna"||e==="quiet_quitter"||e==="slack_spammer"){const n="https://raw.githubusercontent.com/Booby-Boobs/pre-mortem/main/public/",g={slacker:`${n}slacker.png`,control_freak:`${n}control-freak.png`,prima_donna:`${n}prima-donna.png`,quiet_quitter:`${n}quet-quitter.png`,slack_spammer:`${n}slack-spammer.png`},u={...a,render:{sprite:{texture:g[e],xScale:i.w/512*2,yScale:i.h/512*2},lineWidth:3,strokeStyle:"#ffffff"}};return e==="quiet_quitter"?o.Bodies.circle(c,t,i.w/2,u):e==="control_freak"?o.Bodies.trapezoid(c,t,i.w,i.h,.5,u):e==="prima_donna"?o.Bodies.polygon(c,t,5,i.w/2,u):e==="slack_spammer"?o.Bodies.polygon(c,t,6,i.w/2,u):o.Bodies.rectangle(c,t,i.w,i.h,u)}else return o.Bodies.rectangle(c,t,i.w,i.h,a)};class w{constructor(t){l(this,"runway");l(this,"valuation",0);l(this,"stage");l(this,"status","playing");l(this,"lastPenaltyReason","");l(this,"config");l(this,"currentStageIndex",0);l(this,"listeners",[]);if(this.config=t,this.runway=t.initialRunway,!this.config.stages||this.config.stages.length===0)throw new Error("Game must have at least one stage defined.");this.config.stages.sort((e,i)=>e.threshold-i.threshold),this.currentStageIndex=0,this.stage=this.config.stages[0].name,this.checkStage()}setPaused(t){t?this.status==="playing"&&(this.status="paused"):this.status==="paused"&&(this.status="playing"),this.notify()}togglePause(){this.setPaused(this.status==="playing")}tick(t){if(this.status!=="playing")return;const e=Math.min(t,.1),i=this.getDynamicBurnRate();this.runway-=i*e,this.runway<=0&&(this.runway=0,this.status="bankrupt");const s=this.config.stages[this.config.stages.length-1];this.valuation>=s.threshold&&this.status==="playing"&&(this.status="exited"),this.checkStage(),this.notify()}getDynamicBurnRate(){return this.config.stages[this.currentStageIndex].burnRate}addValuation(t){this.valuation+=t,this.checkStage(),this.notify()}spendMoney(t){this.runway-=t,this.notify()}addMoney(t){this.runway+=t,this.notify()}setCollapsed(){this.status==="playing"&&(this.status="collapsed",this.notify())}getNextStageThreshold(){return this.currentStageIndex<this.config.stages.length-1?this.config.stages[this.currentStageIndex+1].threshold:this.config.stages[this.config.stages.length-1].threshold}penalty(t,e){this.runway-=t,this.lastPenaltyReason=e,this.runway<0&&(this.runway=0,this.status="bankrupt"),this.notify("penalty")}checkStage(){let t=0;for(let e=0;e<this.config.stages.length&&this.valuation>=this.config.stages[e].threshold;e++)t=e;if(t!==this.currentStageIndex){if(t>this.currentStageIndex){const e=this.config.stages[t].fundingBonus||0;e>0&&(this.addMoney(e),this.notify("funding:"+e))}this.currentStageIndex=t,this.stage=this.config.stages[t].name}}subscribe(t){this.listeners.push(t)}notify(t){this.listeners.forEach(e=>e(t))}isPlaying(){return this.status==="playing"}isBankrupt(){return this.status==="bankrupt"}}class b{constructor(t,e={}){l(this,"engine");l(this,"render");l(this,"runner");l(this,"container");l(this,"width");l(this,"height");l(this,"mouseConstraint");l(this,"currentQuote",null);l(this,"chaosTimer",1e4);l(this,"chaosInterval",9e4);l(this,"onCrisis");l(this,"gameState");l(this,"spawnVertical",!1);this.container=t,this.width=e.width||t.clientWidth||800,this.height=e.height||t.clientHeight||600,this.onCrisis=e.onCrisis,this.chaosInterval=e.chaosInterval||9e4,this.chaosTimer=e.chaosInterval?e.chaosInterval:1e4;const i=[{name:"Seed Round",threshold:0,burnRate:2e3},{name:"Series A",threshold:1e8,burnRate:1e4,fundingBonus:25e4},{name:"Series B",threshold:25e7,burnRate:25e3,fundingBonus:5e5},{name:"Series C",threshold:5e8,burnRate:5e4,fundingBonus:1e6},{name:"Series D",threshold:7e8,burnRate:75e3,fundingBonus:2e6},{name:"Series E",threshold:85e7,burnRate:1e5,fundingBonus:5e6},{name:"Unicorn Status",threshold:1e9,burnRate:15e4,fundingBonus:1e7}];this.gameState=new w({initialRunway:e.initialRunway||2e5,stages:e.stages||i}),this.engine=o.Engine.create(),this.render=o.Render.create({element:this.container,engine:this.engine,options:{width:this.width,height:this.height,wireframes:!1,background:"#1a1a1a"}}),this.runner=o.Runner.create(),this.initWorld(),this.initMouse(),this.initRenderLoop(),this.initGameLoop(),this.initControls(),this.gameState.subscribe(()=>{this.gameState.status==="paused"?this.runner.enabled=!1:this.gameState.status==="playing"&&(this.runner.enabled=!0)})}initControls(){window.addEventListener("keydown",t=>{(t.key==="r"||t.key==="R")&&this.gameState.isPlaying()&&this.rotateHeldBody()})}rotateHeldBody(){const t=this.mouseConstraint.body;t&&o.Body.rotate(t,45*(Math.PI/180))}initWorld(){const{width:t,height:e}=this,i=60,s=o.Bodies.rectangle(t/2,e-i/2,t,i,{isStatic:!0,render:{fillStyle:"#333"}});o.Composite.add(this.engine.world,[s])}initMouse(){const t=o.Mouse.create(this.render.canvas);this.mouseConstraint=o.MouseConstraint.create(this.engine,{mouse:t,constraint:{stiffness:.2,render:{visible:!1}}}),o.Composite.add(this.engine.world,this.mouseConstraint),this.render.mouse=t}start(){o.Render.run(this.render),o.Runner.run(this.runner,this.engine)}stop(){o.Render.stop(this.render),o.Runner.stop(this.runner)}initRenderLoop(){o.Events.on(this.render,"afterRender",()=>{const t=this.render.context,e=this.width/2,i=400,s=700,a=100,n={x:e-i/2,y:a,w:i,h:this.height-a},g={x:e-s/2,y:a-50,w:s,h:this.height-a+100};if(t.beginPath(),t.setLineDash([10,10]),t.lineWidth=2,t.strokeStyle="rgba(255, 255, 255, 0.3)",t.strokeRect(n.x,n.y,n.w,n.h),t.font='10px "Inter", sans-serif',t.fillStyle="rgba(255, 255, 255, 0.3)",t.textAlign="center",t.fillText("ACCURATE VALUATION ZONE",e,n.y-15),!this.currentQuote){const h=[{text:`WE ARE A
2
2
  FAMILY`,author:"- CEO"},{text:`CHANGE THE
3
3
  WORLD`,author:"- Founder"},{text:`DISRUPT
4
4
  EVERYTHING`,author:"- VC"},{text:`MOVE FAST
@@ -7,8 +7,8 @@ CANDOR`,author:"- HR"},{text:`UNLIMITED
7
7
  PTO`,author:"- Recruiter"},{text:`VISIONARY
8
8
  LEADER`,author:"- LinkedIn"},{text:`10X
9
9
  GROWTH`,author:"- Investor"},{text:`PIVOT
10
- TO AI`,author:"- Board"}];this.currentQuote=u[Math.floor(Math.random()*u.length)]}t.save(),t.translate(e,o.y+o.h/3),t.rotate(-Math.PI/12),t.textAlign="center",t.textBaseline="middle",t.font='900 48px "Inter", sans-serif',t.fillStyle="rgba(255, 255, 255, 0.05)";const p=this.currentQuote.text.split(`
11
- `);p.forEach((u,r)=>t.fillText(u,0,r*50)),t.font='italic 700 24px "Inter", sans-serif',t.fillStyle="rgba(255, 255, 255, 0.04)",t.fillText(this.currentQuote.author,0,p.length*50+10),t.restore(),t.beginPath(),t.setLineDash([]),t.lineWidth=1,t.strokeStyle="rgba(255, 50, 50, 0.2)",t.strokeRect(h.x,h.y,h.w,h.h),t.font='bold 13px "Inter", sans-serif',t.textAlign="center",t.textBaseline="middle",t.fillStyle="#FFFFFF",this.engine.world.bodies.forEach(u=>{if(!u.label||u.label.includes("Body")||u.isStatic)return;const r=u.gameData,m=r&&r.vested;t.save(),t.translate(u.position.x,u.position.y),t.rotate(u.angle),m?(t.shadowColor="#00ff7f",t.shadowBlur=10,t.fillStyle="#00ff7f",t.fillText(u.label+" ✓",0,0)):(t.shadowColor="black",t.shadowBlur=4,t.fillStyle="#FFFFFF",t.fillText(u.label,0,0)),t.restore()})})}initGameLoop(){n.Events.on(this.runner,"afterUpdate",()=>{if(!this.gameState.isPlaying())return;const t=this.runner.delta;this.gameState.tick(t/1e3),this.gameState.valuation>=1e6&&(this.chaosTimer-=t,this.chaosTimer<=0&&(this.triggerChaosEvent(),this.chaosTimer=this.chaosInterval));const e=this.width/2,i=400,s=700;this.engine.world.bodies.forEach(a=>{if(a.isStatic)return;const o=a.gameData;if(Math.abs(a.position.x-e)>s/2||a.position.y>this.height+50){n.Composite.remove(this.engine.world,a);const p=["VC Scolding!","Server Outage!","GDPR Violation!","TechCrunch Hit Piece!","IP Lawsuit!"];this.gameState.penalty(5e4,p[Math.floor(Math.random()*p.length)]);return}if(o&&!o.vested){const p=a.speed<.15&&Math.abs(a.angularVelocity)<.05,u=Math.abs(a.position.x-e)<i/2;p&&u?(o.vestTimer+=this.runner.delta,o.vestTimer>1e3&&(o.vested=!0,this.gameState.addValuation(o.value))):o.vestTimer=0}})})}triggerChaosEvent(){var e,i,s,a,o;switch(Math.floor(Math.random()*5)){case 0:(e=this.onCrisis)==null||e.call(this,"STRATEGIC PIVOT","CEO: 'We are pivoting to AI!' (Gravity Shift)"),this.engine.world.gravity.x=.2,setTimeout(()=>{this.engine.world.gravity.x=0},5e3);break;case 1:(i=this.onCrisis)==null||i.call(this,"THE BIG REORG","HR: 'New Org Chart Announced!' (No Friction)"),this.engine.world.bodies.forEach(r=>{r.isStatic||(r.oldFriction=r.friction,r.friction=0,r.frictionStatic=0)}),setTimeout(()=>{this.engine.world.bodies.forEach(r=>{r.isStatic||(r.friction=r.oldFriction||.1,r.frictionStatic=.5)})},5e3);break;case 2:(s=this.onCrisis)==null||s.call(this,"LEGACY DEPRECATION","CTO: 'Deprecating v1 API!' (Ghost Blocks)");const h=this.engine.world.bodies.filter(r=>!r.isStatic);if(h.length>3){const r=h[Math.floor(Math.random()*h.length)];r.isSensor=!0,setTimeout(()=>{r.isSensor=!1},4e3)}break;case 3:(a=this.onCrisis)==null||a.call(this,"FEATURE CREEP","PM: 'Just one more feature...' (1.2x Scaling)"),this.engine.world.bodies.forEach(r=>{r.isStatic||n.Body.scale(r,1.2,1.2)});break;case 4:(o=this.onCrisis)==null||o.call(this,"VIRAL SPIKE","DevOps: 'Traffic Spike!' (Earthquake)");let p=0;const u=setInterval(()=>{this.engine.world.bodies.forEach(r=>{r.isStatic||n.Body.applyForce(r,r.position,{x:(Math.random()-.5)*.05,y:(Math.random()-.5)*.05})}),++p>20&&clearInterval(u)},100);break}}toggleRotation(){this.spawnVertical=!this.spawnVertical}spawnBlock(t){if(!this.gameState.isPlaying())return;if(Math.random()<1/15){const a=[d.SLACKER,d.CONTROL_FREAK,d.PRIMA_DONNA,d.QUIET_QUITTER,d.SLACK_SPAMMER];t=a[Math.floor(Math.random()*a.length)]}t===d.BOOTSTRAP?this.gameState.spendMoney(5e3):t===d.VC&&this.gameState.addMoney(75e3);const e=this.width/2+(Math.random()-.5)*40,i=v(e,S,t);let s=this.spawnVertical?90*(Math.PI/180):0;t===d.VC&&(s+=(Math.random()-.5)*(30*(Math.PI/180))),n.Body.setAngle(i,s),i.gameData={type:t,value:t===d.VC?5e7:t===d.BOOTSTRAP?5e6:0,vested:!1,vestTimer:0},n.Composite.add(this.engine.world,i)}}const S=100;class x{constructor(t,e){l(this,"container");l(this,"options");l(this,"hudElement");this.container=t,this.options=e,this.initStyles(),this.createHUD(),this.createControls(),this.createLegend(),this.createSystemButtons(),this.options.gameState.subscribe(i=>{if(this.updateHUD(),i==="penalty")this.showToast(`-${this.options.gameState.lastPenaltyReason}`,"danger");else if(i!=null&&i.startsWith("funding:")){const s=i.split(":")[1];this.showToast(`+$${parseInt(s).toLocaleString()} Series Funding!`,"info")}}),this.updateHUD()}initStyles(){const t=document.createElement("style");t.textContent=`
10
+ TO AI`,author:"- Board"}];this.currentQuote=h[Math.floor(Math.random()*h.length)]}t.save(),t.translate(e,n.y+n.h/3),t.rotate(-Math.PI/12),t.textAlign="center",t.textBaseline="middle",t.font='900 48px "Inter", sans-serif',t.fillStyle="rgba(255, 255, 255, 0.05)";const u=this.currentQuote.text.split(`
11
+ `);u.forEach((h,r)=>t.fillText(h,0,r*50)),t.font='italic 700 24px "Inter", sans-serif',t.fillStyle="rgba(255, 255, 255, 0.04)",t.fillText(this.currentQuote.author,0,u.length*50+10),t.restore(),t.beginPath(),t.setLineDash([]),t.lineWidth=1,t.strokeStyle="rgba(255, 50, 50, 0.2)",t.strokeRect(g.x,g.y,g.w,g.h),t.font='bold 13px "Inter", sans-serif',t.textAlign="center",t.textBaseline="middle",t.fillStyle="#FFFFFF",this.engine.world.bodies.forEach(h=>{if(!h.label||h.label.includes("Body")||h.isStatic)return;const r=h.gameData,m=r&&r.vested;t.save(),t.translate(h.position.x,h.position.y),t.rotate(h.angle),m?(t.shadowColor="#00ff7f",t.shadowBlur=10,t.fillStyle="#00ff7f",t.fillText(h.label+" ✓",0,0)):(t.shadowColor="black",t.shadowBlur=4,t.fillStyle="#FFFFFF",t.fillText(h.label,0,0)),t.restore()})})}initGameLoop(){o.Events.on(this.runner,"afterUpdate",()=>{if(!this.gameState.isPlaying())return;const t=this.runner.delta;this.gameState.tick(t/1e3),this.gameState.valuation>=1e6&&(this.chaosTimer-=t,this.chaosTimer<=0&&(this.triggerChaosEvent(),this.chaosTimer=this.chaosInterval));const e=this.width/2,i=400,s=700;this.engine.world.bodies.forEach(a=>{if(a.isStatic)return;const n=a.gameData;if(Math.abs(a.position.x-e)>s/2||a.position.y>this.height+50){o.Composite.remove(this.engine.world,a);const u=["VC Scolding!","Server Outage!","GDPR Violation!","TechCrunch Hit Piece!","IP Lawsuit!"];this.gameState.penalty(5e4,u[Math.floor(Math.random()*u.length)]);return}if(n&&!n.vested){const u=a.speed<.15&&Math.abs(a.angularVelocity)<.05,h=Math.abs(a.position.x-e)<i/2;u&&h?(n.vestTimer+=this.runner.delta,n.vestTimer>1e3&&(n.vested=!0,this.gameState.addValuation(n.value))):n.vestTimer=0}})})}triggerChaosEvent(){var e,i,s,a,n;switch(Math.floor(Math.random()*5)){case 0:(e=this.onCrisis)==null||e.call(this,"STRATEGIC PIVOT","CEO: 'We are pivoting to AI!' (Gravity Shift)"),this.engine.world.gravity.x=.2,setTimeout(()=>{this.engine.world.gravity.x=0},5e3);break;case 1:(i=this.onCrisis)==null||i.call(this,"THE BIG REORG","HR: 'New Org Chart Announced!' (No Friction)"),this.engine.world.bodies.forEach(r=>{r.isStatic||(r.oldFriction=r.friction,r.friction=0,r.frictionStatic=0)}),setTimeout(()=>{this.engine.world.bodies.forEach(r=>{r.isStatic||(r.friction=r.oldFriction||.1,r.frictionStatic=.5)})},5e3);break;case 2:(s=this.onCrisis)==null||s.call(this,"LEGACY DEPRECATION","CTO: 'Deprecating v1 API!' (Ghost Blocks)");const g=this.engine.world.bodies.filter(r=>!r.isStatic);if(g.length>3){const r=g[Math.floor(Math.random()*g.length)];r.isSensor=!0,setTimeout(()=>{r.isSensor=!1},4e3)}break;case 3:(a=this.onCrisis)==null||a.call(this,"FEATURE CREEP","PM: 'Just one more feature...' (1.2x Scaling)"),this.engine.world.bodies.forEach(r=>{r.isStatic||o.Body.scale(r,1.2,1.2)});break;case 4:(n=this.onCrisis)==null||n.call(this,"VIRAL SPIKE","DevOps: 'Traffic Spike!' (Earthquake)");let u=0;const h=setInterval(()=>{this.engine.world.bodies.forEach(r=>{r.isStatic||o.Body.applyForce(r,r.position,{x:(Math.random()-.5)*.05,y:(Math.random()-.5)*.05})}),++u>20&&clearInterval(h)},100);break}}toggleRotation(){this.spawnVertical=!this.spawnVertical}spawnBlock(t){if(!this.gameState.isPlaying())return;if(Math.random()<1/15){const a=[d.SLACKER,d.CONTROL_FREAK,d.PRIMA_DONNA,d.QUIET_QUITTER,d.SLACK_SPAMMER];t=a[Math.floor(Math.random()*a.length)]}t===d.BOOTSTRAP?this.gameState.spendMoney(5e3):t===d.VC&&this.gameState.addMoney(75e3);const e=this.width/2+(Math.random()-.5)*40,i=v(e,S,t);let s=this.spawnVertical?90*(Math.PI/180):0;t===d.VC&&(s+=(Math.random()-.5)*(30*(Math.PI/180))),o.Body.setAngle(i,s),i.gameData={type:t,value:t===d.VC?5e7:t===d.BOOTSTRAP?5e6:0,vested:!1,vestTimer:0},o.Composite.add(this.engine.world,i)}}const S=100;class x{constructor(t,e){l(this,"container");l(this,"options");l(this,"hudElement");this.container=t,this.options=e,this.initStyles(),this.createHUD(),this.createControls(),this.createLegend(),this.createSystemButtons(),this.options.gameState.subscribe(i=>{if(this.updateHUD(),i==="penalty")this.showToast(`-${this.options.gameState.lastPenaltyReason}`,"danger");else if(i!=null&&i.startsWith("funding:")){const s=i.split(":")[1];this.showToast(`+$${parseInt(s).toLocaleString()} Series Funding!`,"info")}}),this.updateHUD()}initStyles(){const t=document.createElement("style");t.textContent=`
12
12
  .uj-hud {
13
13
  position: absolute;
14
14
  top: 20px; /* Restored to top */
@@ -326,14 +326,14 @@ TO AI`,author:"- Board"}];this.currentQuote=u[Math.floor(Math.random()*u.length)
326
326
  </div>
327
327
  </div>
328
328
  </div>
329
- `,this.container.appendChild(e),this.populateGlossaryLists();const i=()=>{if(e.remove(),t){this.options.gameState.setPaused(!1);const s=document.getElementById("uj-btn-pause");s&&(s.innerText="⏸ PAUSE")}};document.getElementById("uj-glossary-close").onclick=i,e.onclick=s=>{s.target===e&&i()}}populateGlossaryLists(){var i,s;const t=document.getElementById("uj-solid-list"),e=document.getElementById("uj-hype-list");t&&e&&((i=f[d.BOOTSTRAP].possibleLabels)==null||i.forEach(a=>{const o=document.createElement("li");o.textContent=a,t.appendChild(o)}),(s=f[d.VC].possibleLabels)==null||s.forEach(a=>{const o=document.createElement("li");o.textContent=a,e.appendChild(o)}))}createHUD(){this.hudElement=document.createElement("div"),this.hudElement.className="uj-hud",this.container.appendChild(this.hudElement)}updateHUD(){const t=this.options.gameState,e=new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",maximumFractionDigits:0}),i=new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",notation:"compact",maximumFractionDigits:1}),a=t.isBankrupt()?"uj-stat-value danger":"uj-stat-value",o=t.getNextStageThreshold(),h=o>0?`<small style="font-size:12px; opacity:0.7">Next: ${i.format(o)}</small>`:"";this.hudElement.innerHTML=`
329
+ `,this.container.appendChild(e),this.populateGlossaryLists();const i=()=>{if(e.remove(),t){this.options.gameState.setPaused(!1);const s=document.getElementById("uj-btn-pause");s&&(s.innerText="⏸ PAUSE")}};document.getElementById("uj-glossary-close").onclick=i,e.onclick=s=>{s.target===e&&i()}}populateGlossaryLists(){var i,s;const t=document.getElementById("uj-solid-list"),e=document.getElementById("uj-hype-list");t&&e&&((i=f[d.BOOTSTRAP].possibleLabels)==null||i.forEach(a=>{const n=document.createElement("li");n.textContent=a,t.appendChild(n)}),(s=f[d.VC].possibleLabels)==null||s.forEach(a=>{const n=document.createElement("li");n.textContent=a,e.appendChild(n)}))}createHUD(){this.hudElement=document.createElement("div"),this.hudElement.className="uj-hud",this.container.appendChild(this.hudElement)}updateHUD(){const t=this.options.gameState,e=new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",maximumFractionDigits:0}),i=new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",notation:"compact",maximumFractionDigits:1}),a=t.isBankrupt()?"uj-stat-value danger":"uj-stat-value",n=t.getNextStageThreshold(),g=n>0?`<small style="font-size:12px; opacity:0.7">Next: ${i.format(n)}</small>`:"";this.hudElement.innerHTML=`
330
330
  <div class="uj-stat-label">Stage</div>
331
331
  <div class="uj-stat-value">${t.stage}</div>
332
332
 
333
333
  <div class="uj-stat-label">Valuation</div>
334
334
  <div class="uj-stat-value" style="color: #00ff7f">
335
335
  ${e.format(t.valuation)}<br>
336
- ${h}
336
+ ${g}
337
337
  </div>
338
338
 
339
339
  <div class="uj-stat-label">Runway</div>
@@ -363,8 +363,8 @@ TO AI`,author:"- Board"}];this.currentQuote=u[Math.floor(Math.random()*u.length)
363
363
  justify-content: center;
364
364
  z-index: 200;
365
365
  font-family: 'Inter', sans-serif;
366
- `;let s="",a="",o="#fff";switch(t){case"bankrupt":s="HONEST POOR",a="You ran out of runway. The market did not love you.",o="#ff4444";break;case"collapsed":s="SCANDAL!",a="Your tower of lies has collapsed. TechCrunch is mocking you.",o="#ffaa00";break;case"exited":s="VISIONARY FRAUD",a=`You exited with $${(e/1e6).toFixed(1)}M! You are a genius.`,o="#00ff7f";break}i.innerHTML=`
367
- <h1 style="font-size: 48px; color: ${o}; margin-bottom: 10px;">${s}</h1>
366
+ `;let s="",a="",n="#fff";switch(t){case"bankrupt":s="HONEST POOR",a="You ran out of runway. The market did not love you.",n="#ff4444";break;case"collapsed":s="SCANDAL!",a="Your tower of lies has collapsed. TechCrunch is mocking you.",n="#ffaa00";break;case"exited":s="VISIONARY FRAUD",a=`You exited with $${(e/1e6).toFixed(1)}M! You are a genius.`,n="#00ff7f";break}i.innerHTML=`
367
+ <h1 style="font-size: 48px; color: ${n}; margin-bottom: 10px;">${s}</h1>
368
368
  <p style="font-size: 18px; color #ccc; max-width: 400px; text-align: center;">${a}</p>
369
369
  <button onclick="window.location.reload()" style="
370
370
  margin-top: 30px;
@@ -379,4 +379,4 @@ TO AI`,author:"- Board"}];this.currentQuote=u[Math.floor(Math.random()*u.length)
379
379
  `,this.container.appendChild(i)}showLogo(t){if(!t)return;const e=document.createElement("img");e.src=t,e.className="uj-overlay-logo",this.container.appendChild(e)}showCrisisAlert(t,e){const i=document.createElement("div");i.className="uj-crisis-overlay active";const s=document.createElement("div");s.className="uj-crisis-box",s.innerHTML=`
380
380
  <div class="uj-crisis-shout">${t}</div>
381
381
  <div class="uj-crisis-desc">${e}</div>
382
- `,i.appendChild(s),this.container.appendChild(i),setTimeout(()=>s.classList.add("visible"),100),setTimeout(()=>{s.classList.remove("visible"),i.classList.remove("active"),setTimeout(()=>{i.remove()},500)},4e3)}}class k{constructor(t,e={}){l(this,"game");l(this,"ui");this.game=new b(t,{...e,onCrisis:(i,s)=>this.ui.showCrisisAlert(i,s)}),this.ui=new x(t,{onSpawn:i=>this.game.spawnBlock(i),onRotate:()=>this.game.toggleRotation(),gameState:this.game.gameState}),e.logoUrl&&this.ui.showLogo(e.logoUrl)}start(){this.game.start()}}g.PreMortem=k,g.PreMortemGame=b,g.UIManager=x,Object.defineProperty(g,Symbol.toStringTag,{value:"Module"})});
382
+ `,i.appendChild(s),this.container.appendChild(i),setTimeout(()=>s.classList.add("visible"),100),setTimeout(()=>{s.classList.remove("visible"),i.classList.remove("active"),setTimeout(()=>{i.remove()},500)},4e3)}}class k{constructor(t,e={}){l(this,"game");l(this,"ui");this.game=new b(t,{...e,onCrisis:(i,s)=>this.ui.showCrisisAlert(i,s)}),this.ui=new x(t,{onSpawn:i=>this.game.spawnBlock(i),onRotate:()=>this.game.toggleRotation(),gameState:this.game.gameState}),e.logoUrl&&this.ui.showLogo(e.logoUrl)}start(){this.game.start()}}p.PreMortem=k,p.PreMortemGame=b,p.UIManager=x,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pre-mortem",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "The Exit Simulator: A satirical startup physics game",
5
5
  "main": "dist/pre-mortem.umd.js",
6
6
  "module": "dist/pre-mortem.mjs",
@@ -16,6 +16,11 @@
16
16
  "physics",
17
17
  "matter-js"
18
18
  ],
19
+ "files": [
20
+ "dist",
21
+ "README.md",
22
+ "LICENSE"
23
+ ],
19
24
  "author": "Boobs",
20
25
  "license": "ISC",
21
26
  "repository": {
package/index.html DELETED
@@ -1,39 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Pre-Mortem - The Exit Simulator</title>
7
- <style>
8
- body {
9
- margin: 0;
10
- padding: 0;
11
- background: #000;
12
- color: #fff;
13
- font-family: sans-serif;
14
- overflow: hidden;
15
- }
16
- #app {
17
- width: 100vw;
18
- height: 100vh;
19
- position: relative;
20
- }
21
- </style>
22
- </head>
23
- <body>
24
- <div id="app"></div>
25
- <script type="module">
26
- import { PreMortem } from './src/index.ts';
27
-
28
- const app = document.getElementById('app');
29
- // Example Logo: using a placeholder or local asset
30
- // For demo, we leave it empty or use a placeholder
31
- const game = new PreMortem(app, {
32
- logoUrl: './logo.png', // Local logo
33
- width: window.innerWidth,
34
- height: window.innerHeight
35
- });
36
- game.start();
37
- </script>
38
- </body>
39
- </html>
Binary file
package/public/logo.png DELETED
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/src/blocks.ts DELETED
@@ -1,182 +0,0 @@
1
- import Matter from 'matter-js';
2
-
3
- export enum BlockType {
4
- BOOTSTRAP = 'bootstrap',
5
- VC = 'vc',
6
- SLACKER = 'slacker',
7
- CONTROL_FREAK = 'control_freak',
8
- PRIMA_DONNA = 'prima_donna',
9
- QUIET_QUITTER = 'quiet_quitter',
10
- SLACK_SPAMMER = 'slack_spammer'
11
- }
12
-
13
- export interface BlockConfig {
14
- w: number;
15
- h: number;
16
- color: string;
17
- density: number;
18
- friction: number;
19
- restitution: number;
20
- label: string;
21
- possibleLabels?: string[];
22
- }
23
-
24
- export const BLOCK_DEFINITIONS: Record<BlockType, BlockConfig> = {
25
- [BlockType.BOOTSTRAP]: {
26
- w: 132,
27
- h: 44,
28
- color: '#555555', // Concrete/Rust
29
- density: 0.005, // High relative density (Matter.js default is 0.001)
30
- friction: 0.8,
31
- restitution: 0.0,
32
- label: 'Refactoring',
33
- possibleLabels: [
34
- // The Work (Old & New)
35
- 'Refactoring', 'Unit Tests', 'Bug Fixes', 'User Support',
36
- 'Documentation', 'Security Audit', 'Compliance', 'Cleanup',
37
- 'Optimization', 'CI/CD Pipeline', 'Code Review', 'DB Tuning',
38
- 'API Design', 'Accessibility', 'Localization', 'Error Logs',
39
- 'Backups', 'Legacy Code', 'Hiring', 'Customer Love',
40
- 'Bossware', 'YAML Hell', 'DNS Propagation', 'Regex', 'npm audit',
41
- 'GDPR / SOC2', 'Migration', 'Certificate Expiry', 'On-Call',
42
- 'Technical Debt', 'Works on my machine', 'Yak Shaving'
43
- ]
44
- },
45
- [BlockType.VC]: {
46
- w: 120,
47
- h: 40,
48
- color: '#FF00FF', // Neon Pink
49
- density: 0.0005, // Slightly heavier (was 0.0001)
50
- friction: 0.3, // Less slippery (was 0.1)
51
- restitution: 0.6, // Less bouncy (was 0.9)
52
- label: 'AI Blockchain',
53
- possibleLabels: [
54
- // The Hype (Old & New)
55
- 'GenAI', 'Blockchain', 'Web3', 'Metaverse', 'NFTs',
56
- 'Viral Growth', 'Pivot', 'Synergy', 'Disruption',
57
- 'Thought Leader', 'Influencers', 'Hyper-Scale', 'Quantum',
58
- 'Big Data', 'Growth Hack', 'Paradigm Shift', '10x Engineer',
59
- 'Visionary', 'Series B Pitch', 'Exit Strategy',
60
- 'Vibe Coding', 'Founder Mode', 'Prompt Engineering', 'AGI',
61
- 'AI Wrapper', 'Unlimited PTO', 'Radical Candor', 'Community Led',
62
- 'Pre-Revenue', 'Fractional CxO'
63
- ]
64
- },
65
- [BlockType.SLACKER]: {
66
- w: 64, // 80 * 0.8
67
- h: 64, // 80 * 0.8
68
- color: '#FFFFFF',
69
- density: 0.01,
70
- friction: 1.0,
71
- restitution: 0.1,
72
- label: 'The Slacker',
73
- possibleLabels: ['The Slacker']
74
- },
75
- [BlockType.CONTROL_FREAK]: {
76
- w: 64, // Square to match image aspect ratio
77
- h: 64,
78
- color: '#FF0000', density: 0.012, friction: 0.5, restitution: 0.2,
79
- label: 'Control Freak', possibleLabels: ['Control Freak']
80
- },
81
- [BlockType.PRIMA_DONNA]: {
82
- w: 56, h: 56, // 70 * 0.8
83
- color: '#FFFF00', density: 0.008, friction: 0.1, restitution: 1.2,
84
- label: 'Prima Donna', possibleLabels: ['Prima Donna']
85
- },
86
- [BlockType.QUIET_QUITTER]: {
87
- w: 48, h: 48, // 60 * 0.8
88
- color: '#00FFFF', density: 0.005, friction: 0.01, restitution: 0.9,
89
- label: 'Quiet Quitter', possibleLabels: ['Quiet Quitter']
90
- },
91
- [BlockType.SLACK_SPAMMER]: {
92
- w: 60, h: 60, // 75 * 0.8
93
- color: '#00FF00', density: 0.01, friction: 0.4, restitution: 0.4,
94
- label: 'Slack Spammer', possibleLabels: ['Slack Spammer']
95
- }
96
- };
97
-
98
- export const getRandomLabel = (type: BlockType): string => {
99
- const labels = BLOCK_DEFINITIONS[type].possibleLabels || [];
100
- return labels[Math.floor(Math.random() * labels.length)];
101
- }
102
-
103
- export const createBlock = (x: number, y: number, type: BlockType) => {
104
- const def = BLOCK_DEFINITIONS[type];
105
- const labelText = getRandomLabel(type);
106
-
107
- const options = {
108
- density: def.density,
109
- friction: def.friction,
110
- restitution: def.restitution,
111
- render: {
112
- fillStyle: def.color,
113
- strokeStyle: '#000',
114
- lineWidth: 2,
115
- },
116
- label: labelText,
117
- };
118
-
119
- if (type === BlockType.VC) {
120
- // "Long Side Trapezoid" / Distorted Wedge
121
- // Create an irregular quadrilateral that is annoying to stack
122
- const w = def.w;
123
- const h = def.h;
124
-
125
- // Randomize the top corners to create a slanted roof (Wedge)
126
- // or skew the sides (Parallelogram)
127
- const y1 = Math.random() * 15; // Top-Left drop
128
- const y2 = Math.random() * 15; // Top-Right drop
129
- const skew = (Math.random() - 0.5) * 20; // skew x
130
-
131
- const vertices = [
132
- { x: 0 + skew, y: y1 }, // TL
133
- { x: w + skew, y: y2 }, // TR
134
- { x: w, y: h }, // BR
135
- { x: 0, y: h } // BL
136
- ];
137
-
138
- return Matter.Bodies.fromVertices(x, y, [vertices], options);
139
- return Matter.Bodies.fromVertices(x, y, [vertices], options);
140
- } else if (type === BlockType.SLACKER ||
141
- type === BlockType.CONTROL_FREAK ||
142
- type === BlockType.PRIMA_DONNA ||
143
- type === BlockType.QUIET_QUITTER ||
144
- type === BlockType.SLACK_SPAMMER) {
145
-
146
- const textureMap: Record<string, string> = {
147
- [BlockType.SLACKER]: './slacker.png',
148
- [BlockType.CONTROL_FREAK]: './control-freak.png',
149
- [BlockType.PRIMA_DONNA]: './prima-donna.png',
150
- [BlockType.QUIET_QUITTER]: './quet-quitter.png', // User typo kept
151
- [BlockType.SLACK_SPAMMER]: './slack-spammer.png'
152
- };
153
-
154
- const spriteOptions = {
155
- ...options,
156
- render: {
157
- sprite: {
158
- texture: textureMap[type],
159
- xScale: (def.w / 512) * 2, // Approximate
160
- yScale: (def.h / 512) * 2
161
- },
162
- lineWidth: 3,
163
- strokeStyle: '#ffffff'
164
- }
165
- };
166
-
167
- if (type === BlockType.QUIET_QUITTER) {
168
- return Matter.Bodies.circle(x, y, def.w / 2, spriteOptions);
169
- } else if (type === BlockType.CONTROL_FREAK) {
170
- return Matter.Bodies.trapezoid(x, y, def.w, def.h, 0.5, spriteOptions);
171
- } else if (type === BlockType.PRIMA_DONNA) {
172
- return Matter.Bodies.polygon(x, y, 5, def.w / 2, spriteOptions); // Pentagon
173
- } else if (type === BlockType.SLACK_SPAMMER) {
174
- return Matter.Bodies.polygon(x, y, 6, def.w / 2, spriteOptions); // Hexagon
175
- } else {
176
- // Default Slacker (Square)
177
- return Matter.Bodies.rectangle(x, y, def.w, def.h, spriteOptions);
178
- }
179
- } else {
180
- return Matter.Bodies.rectangle(x, y, def.w, def.h, options);
181
- }
182
- };