Ver Fonte

tweak engine

clovis há 1 mês atrás
pai
commit
0bf10837af

+ 97 - 39
src/assets/components/BeaconConfigurator.tsx

@@ -14,69 +14,127 @@ export type BeaconGroup = {
   modules: { module: Module; qualityLevel: number }[];
 };
 
-export default function BeaconConfigurator({ groups, onChange }: { groups: BeaconGroup[], onChange: (g: BeaconGroup[]) => void }) {
+function BeaconIconWrapper({
+  beacon,
+  onChangeQuality,
+}: {
+  beacon: Beacon;
+  onChangeQuality: (qualityLevel: number) => void;
+}) {
+  const { scrollRef, activeQuality } = useQualityScroller("normal", (q) => onChangeQuality(q.level));
+  return (
+    <div
+      ref={scrollRef}
+      style={{ display: "flex", flexDirection: "column", alignItems: "center", cursor: "ns-resize", gap: "4px" }}
+      title="Shift+Scroll to change beacon quality"
+    >
+      <label style={{ fontSize: "11px", color: "#999" }}>Beacon</label>
+      <Icon iconName={beacon.icon ?? ""} size={44} qualityLevel={activeQuality.level} />
+    </div>
+  );
+}
+export default function BeaconConfigurator({
+  groups,
+  onChange,
+}: {
+  groups: BeaconGroup[];
+  onChange: (g: BeaconGroup[]) => void;
+}) {
   const handleAddGroup = () => {
     const defaultBeacon = beaconsData[0];
-    onChange([...groups, {
-      id: Date.now().toString(),
-      beacon: defaultBeacon,
-      qualityLevel: 0,
-      count: 1,
-      modules: []
-    }]);
+    onChange([
+      ...groups,
+      {
+        id: Date.now().toString(),
+        beacon: defaultBeacon,
+        qualityLevel: 0,
+        count: 1,
+        modules: [],
+      },
+    ]);
   };
 
   const updateGroup = (id: string, patch: Partial<BeaconGroup>) => {
-    onChange(groups.map(g => g.id === id ? { ...g, ...patch } : g));
+    onChange(groups.map((g) => (g.id === id ? { ...g, ...patch } : g)));
   };
 
   return (
     <div style={{ display: "flex", flexDirection: "column", gap: "10px" }}>
       {groups.map((g) => (
-        <div key={g.id} style={{ display: "flex", gap: "16px", alignItems: "center", background: "#242324", padding: "8px", borderRadius: "4px", border: "1px solid #3a3a3a" }}>
-          
+        <div
+          key={g.id}
+          style={{
+            display: "flex",
+            gap: "16px",
+            alignItems: "center",
+            background: "#242324",
+            padding: "8px",
+            borderRadius: "4px",
+            border: "1px solid #3a3a3a",
+          }}
+        >
           {/* Beacon Count */}
           <div style={{ display: "flex", flexDirection: "column", gap: "4px" }}>
             <label style={{ fontSize: "11px", color: "#999" }}>Count</label>
-            <input 
-              type="number" min="1" max="50" 
-              value={g.count} 
-              onChange={e => updateGroup(g.id, { count: Number(e.target.value) || 1 })}
-              style={{ width: "50px", background: "#1a1a1a", color: "#ffe6c0", border: "1px solid #646464", padding: "4px", borderRadius: "4px" }}
+            <input
+              type="number"
+              min="1"
+              max="50"
+              value={g.count}
+              onChange={(e) => updateGroup(g.id, { count: Number(e.target.value) || 1 })}
+              style={{
+                width: "50px",
+                background: "#1a1a1a",
+                color: "#ffe6c0",
+                border: "1px solid #646464",
+                padding: "4px",
+                borderRadius: "4px",
+              }}
             />
           </div>
 
           {/* Beacon Type & Quality */}
-          <BeaconIconWrapper 
-            beacon={g.beacon} 
-            qualityLevel={g.qualityLevel} 
-            onChangeQuality={(q) => updateGroup(g.id, { qualityLevel: q })} 
-          />
+          <BeaconIconWrapper beacon={g.beacon} onChangeQuality={(q) => updateGroup(g.id, { qualityLevel: q })} />
 
           {/* Beacon Modules */}
           <div style={{ display: "flex", flexDirection: "column", gap: "4px" }}>
-             <label style={{ fontSize: "11px", color: "#999" }}>Modules ({g.beacon.module_slots})</label>
-             <ModuleSlots 
-               maxSlots={g.beacon.module_slots} 
-               allowedEffects={g.beacon.allowed_effects as string[]}
-               onChange={mods => updateGroup(g.id, { modules: mods })}
-             />
+            <label style={{ fontSize: "11px", color: "#999" }}>Modules ({g.beacon.module_slots})</label>
+            <ModuleSlots
+              maxSlots={g.beacon.module_slots}
+              allowedEffects={g.beacon.allowed_effects as string[]}
+              onChange={(mods) => updateGroup(g.id, { modules: mods })}
+            />
           </div>
 
-          <button onClick={() => onChange(groups.filter(x => x.id !== g.id))} style={{ marginLeft: "auto", background: "none", border: "none", color: "#d9614f", cursor: "pointer", fontSize: "16px" }}>✕</button>
+          <button
+            onClick={() => onChange(groups.filter((x) => x.id !== g.id))}
+            style={{
+              marginLeft: "auto",
+              background: "none",
+              border: "none",
+              color: "#d9614f",
+              cursor: "pointer",
+              fontSize: "16px",
+            }}
+          >
+            ✕
+          </button>
         </div>
       ))}
-      <button onClick={handleAddGroup} style={{ alignSelf: "flex-start", background: "none", border: "1px dashed #646464", color: "#999", padding: "6px 12px", borderRadius: "4px", cursor: "pointer" }}>+ Add Beacons</button>
+      <button
+        onClick={handleAddGroup}
+        style={{
+          alignSelf: "flex-start",
+          background: "none",
+          border: "1px dashed #646464",
+          color: "#999",
+          padding: "6px 12px",
+          borderRadius: "4px",
+          cursor: "pointer",
+        }}
+      >
+        + Add Beacons
+      </button>
     </div>
   );
 }
-
-function BeaconIconWrapper({ beacon, qualityLevel, onChangeQuality }: any) {
-  const { scrollRef, activeQuality } = useQualityScroller("normal", (q) => onChangeQuality(q.level));
-  return (
-    <div ref={scrollRef} style={{ display: "flex", flexDirection: "column", alignItems: "center", cursor: "ns-resize", gap: "4px" }} title="Shift+Scroll to change beacon quality">
-       <label style={{ fontSize: "11px", color: "#999" }}>Beacon</label>
-       <Icon iconName={beacon.icon ?? ""} size={44} qualityLevel={activeQuality.level} />
-    </div>
-  );
-}

+ 3 - 0
src/engine/error.txt

@@ -0,0 +1,3 @@
+Uncaught InternalError: too much recursion
+    gcd factorioEngine.ts:7
+    gcd factorioEngine.ts:7

+ 16 - 9
src/engine/factorioEngine.ts

@@ -47,7 +47,7 @@ export interface CalculatedTimings {
   actualCraftingSpeed: number;
   productivityBonus: number;
   singleCraftTicks: number;
-  craftsPerSecond: number; // NEW: Useful for scaling / target throughput
+  craftsPerSecond: number;
   overloadMultiplier: number;
 }
 
@@ -60,9 +60,19 @@ export interface BatchPlan {
 }
 
 function getQualityMultiplier(level: number): number {
-  if (level === 4) return 2.5;
   return 1 + level * 0.3;
 }
+function getBeaconOverlapPenalty(beacon: Beacon, overlapCount: number): number {
+  if (beacon.profile && beacon.profile.length < overlapCount) {
+    return beacon.profile[overlapCount];
+  }
+  // Default to fomula
+  return 1 / Math.sqrt(overlapCount);
+}
+function getTransmissionStrength(b: Beacon, overlapCount: number, qualityLevel: number = 0): number {
+  const qualityBonus = (b.distribution_effectivity_bonus_per_quality_level ?? 0) * qualityLevel;
+  return (b.distribution_effectivity + qualityBonus) * getBeaconOverlapPenalty(b, overlapCount);
+}
 
 // ---  Machine Stats Calculator ---
 export function computeMachineStats(setup: MachineSetup, recipe: Recipe): CalculatedTimings {
@@ -79,12 +89,8 @@ export function computeMachineStats(setup: MachineSetup, recipe: Recipe): Calcul
     if (module.effect?.productivity) productivityBonus += module.effect.productivity * modQualityMultiplier;
   });
 
-  let beaconCount = Math.sqrt(setup.beacons.reduce((acc, b) => acc + b.count, 0));
+  let beaconCount = setup.beacons.reduce((acc, b) => acc + b.count, 0);
   setup.beacons.forEach((b) => {
-    const beaconQualityLevel = b.beaconQualityLevel ?? 0;
-    const effectivityBonus = (b.beacon.distribution_effectivity_bonus_per_quality_level ?? 0) * beaconQualityLevel;
-    const distributionEffectivity = b.beacon.distribution_effectivity + effectivityBonus;
-
     let beaconSpeed = 0;
     let beaconProd = 0;
 
@@ -94,8 +100,9 @@ export function computeMachineStats(setup: MachineSetup, recipe: Recipe): Calcul
       if (module.effect?.productivity) beaconProd += module.effect.productivity * modQualityMultiplier;
     });
 
-    speedBonus += ((beaconSpeed * distributionEffectivity) / beaconCount) * b.count;
-    productivityBonus += ((beaconProd * distributionEffectivity) / beaconCount) * b.count;
+    const transmissionStrength = getTransmissionStrength(b.beacon, beaconCount, b.beaconQualityLevel);
+    speedBonus += beaconSpeed * transmissionStrength * b.count;
+    productivityBonus += beaconProd * transmissionStrength * b.count;
   });
 
   const effectiveSpeedMultiplier = Math.max(0.2, 1 + speedBonus);