mirror of
https://github.com/setube/ogame-vue-ts.git
synced 2026-05-12 16:05:12 +08:00
优化
This commit is contained in:
345
src/logic/productionLogic.ts
Normal file
345
src/logic/productionLogic.ts
Normal file
@@ -0,0 +1,345 @@
|
||||
/**
|
||||
* 生产计算纯函数
|
||||
* 所有函数都是纯函数:无副作用,相同输入总是产生相同输出
|
||||
* 便于单元测试和服务端复用
|
||||
*/
|
||||
|
||||
import type { Planet, Resources } from '@/types/game'
|
||||
import { BuildingType } from '@/types/game'
|
||||
|
||||
/**
|
||||
* 生产加成配置
|
||||
*/
|
||||
export interface ProductionBonuses {
|
||||
/** 能量生产加成百分比 */
|
||||
energyProductionBonus: number
|
||||
/** 存储容量加成百分比 */
|
||||
storageCapacityBonus: number
|
||||
/** 资源速度倍率 */
|
||||
resourceSpeed: number
|
||||
}
|
||||
|
||||
/**
|
||||
* 科技加成配置
|
||||
*/
|
||||
export interface TechBonuses {
|
||||
/** 金属采矿研究等级 */
|
||||
mineralResearchLevel: number
|
||||
/** 晶体采矿研究等级 */
|
||||
crystalResearchLevel: number
|
||||
/** 燃料研究等级 */
|
||||
fuelResearchLevel: number
|
||||
}
|
||||
|
||||
/**
|
||||
* 生产计算结果
|
||||
*/
|
||||
export interface ProductionResult {
|
||||
/** 资源生产量(每秒) */
|
||||
production: Resources
|
||||
/** 能量生产量 */
|
||||
energyProduction: number
|
||||
/** 能量消耗量 */
|
||||
energyConsumption: number
|
||||
/** 能量比率(0-1) */
|
||||
energyRatio: number
|
||||
/** 存储容量 */
|
||||
capacity: Resources
|
||||
}
|
||||
|
||||
// 基础配置常量
|
||||
const BASE_ENERGY_PRODUCTION = 0
|
||||
const BASE_METAL_PRODUCTION = 10
|
||||
const BASE_CRYSTAL_PRODUCTION = 5
|
||||
const BASE_DEUTERIUM_PRODUCTION = 0
|
||||
const BASE_STORAGE_CAPACITY = 10000
|
||||
const STORAGE_CAPACITY_FACTOR = 2
|
||||
const RESEARCH_PRODUCTION_BONUS_PER_LEVEL = 0.02
|
||||
|
||||
// 能量生产配置
|
||||
const SOLAR_PLANT_BASE = 50
|
||||
const SOLAR_PLANT_FACTOR = 1.1
|
||||
const FUSION_REACTOR_BASE = 150
|
||||
const FUSION_REACTOR_FACTOR = 1.15
|
||||
|
||||
// 能量消耗配置
|
||||
const METAL_MINE_ENERGY_BASE = 10
|
||||
const METAL_MINE_ENERGY_FACTOR = 1.1
|
||||
const CRYSTAL_MINE_ENERGY_BASE = 10
|
||||
const CRYSTAL_MINE_ENERGY_FACTOR = 1.1
|
||||
const DEUTERIUM_SYNTH_ENERGY_BASE = 15
|
||||
const DEUTERIUM_SYNTH_ENERGY_FACTOR = 1.1
|
||||
|
||||
// 资源生产配置(每小时)
|
||||
const METAL_MINE_PRODUCTION_BASE = 30
|
||||
const METAL_MINE_PRODUCTION_FACTOR = 1.1
|
||||
const CRYSTAL_MINE_PRODUCTION_BASE = 20
|
||||
const CRYSTAL_MINE_PRODUCTION_FACTOR = 1.1
|
||||
const DEUTERIUM_SYNTH_PRODUCTION_BASE = 10
|
||||
const DEUTERIUM_SYNTH_PRODUCTION_FACTOR = 1.1
|
||||
|
||||
// 核聚变反应堆重氢消耗
|
||||
const FUSION_DEUTERIUM_BASE = 10
|
||||
const FUSION_DEUTERIUM_FACTOR = 1.1
|
||||
|
||||
/**
|
||||
* 计算科技生产加成
|
||||
* @pure
|
||||
*/
|
||||
export const calcTechProductionBonus = (
|
||||
mineralResearchLevel: number = 0,
|
||||
crystalResearchLevel: number = 0,
|
||||
fuelResearchLevel: number = 0
|
||||
): { metalBonus: number; crystalBonus: number; deuteriumBonus: number } => {
|
||||
return {
|
||||
metalBonus: mineralResearchLevel * RESEARCH_PRODUCTION_BONUS_PER_LEVEL,
|
||||
crystalBonus: crystalResearchLevel * RESEARCH_PRODUCTION_BONUS_PER_LEVEL,
|
||||
deuteriumBonus: fuelResearchLevel * RESEARCH_PRODUCTION_BONUS_PER_LEVEL
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算能量生产(纯函数)
|
||||
* @pure
|
||||
*/
|
||||
export const calcEnergyProduction = (planet: Planet, energyProductionBonus: number = 0): number => {
|
||||
let totalEnergy = BASE_ENERGY_PRODUCTION
|
||||
|
||||
// 太阳能电站
|
||||
const solarPlantLevel = planet.buildings[BuildingType.SolarPlant] || 0
|
||||
if (solarPlantLevel > 0) {
|
||||
totalEnergy += Math.floor(SOLAR_PLANT_BASE * solarPlantLevel * Math.pow(SOLAR_PLANT_FACTOR, solarPlantLevel))
|
||||
}
|
||||
|
||||
// 核聚变反应堆
|
||||
const fusionReactorLevel = planet.buildings[BuildingType.FusionReactor] || 0
|
||||
if (fusionReactorLevel > 0) {
|
||||
totalEnergy += Math.floor(FUSION_REACTOR_BASE * fusionReactorLevel * Math.pow(FUSION_REACTOR_FACTOR, fusionReactorLevel))
|
||||
}
|
||||
|
||||
// 应用加成
|
||||
return Math.floor(totalEnergy * (1 + energyProductionBonus))
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算能量消耗(纯函数)
|
||||
* @pure
|
||||
*/
|
||||
export const calcEnergyConsumption = (planet: Planet): number => {
|
||||
let totalConsumption = 0
|
||||
|
||||
// 金属矿
|
||||
const metalMineLevel = planet.buildings[BuildingType.MetalMine] || 0
|
||||
if (metalMineLevel > 0) {
|
||||
totalConsumption += Math.floor(METAL_MINE_ENERGY_BASE * metalMineLevel * Math.pow(METAL_MINE_ENERGY_FACTOR, metalMineLevel))
|
||||
}
|
||||
|
||||
// 晶体矿
|
||||
const crystalMineLevel = planet.buildings[BuildingType.CrystalMine] || 0
|
||||
if (crystalMineLevel > 0) {
|
||||
totalConsumption += Math.floor(CRYSTAL_MINE_ENERGY_BASE * crystalMineLevel * Math.pow(CRYSTAL_MINE_ENERGY_FACTOR, crystalMineLevel))
|
||||
}
|
||||
|
||||
// 重氢合成器
|
||||
const deuteriumSynthesizerLevel = planet.buildings[BuildingType.DeuteriumSynthesizer] || 0
|
||||
if (deuteriumSynthesizerLevel > 0) {
|
||||
totalConsumption += Math.floor(
|
||||
DEUTERIUM_SYNTH_ENERGY_BASE * deuteriumSynthesizerLevel * Math.pow(DEUTERIUM_SYNTH_ENERGY_FACTOR, deuteriumSynthesizerLevel)
|
||||
)
|
||||
}
|
||||
|
||||
return totalConsumption
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算资源生产量(纯函数)
|
||||
* @pure
|
||||
* @param planet 星球状态
|
||||
* @param energyRatio 能量比率(0-1)
|
||||
* @param techBonuses 科技加成
|
||||
* @returns 每秒资源生产量
|
||||
*/
|
||||
export const calcResourceProduction = (planet: Planet, energyRatio: number, techBonuses?: TechBonuses): Resources => {
|
||||
const effectiveRatio = Math.min(1, Math.max(0, energyRatio))
|
||||
const bonuses = techBonuses
|
||||
? calcTechProductionBonus(techBonuses.mineralResearchLevel, techBonuses.crystalResearchLevel, techBonuses.fuelResearchLevel)
|
||||
: { metalBonus: 0, crystalBonus: 0, deuteriumBonus: 0 }
|
||||
|
||||
// 金属生产
|
||||
let metalProduction = BASE_METAL_PRODUCTION
|
||||
const metalMineLevel = planet.buildings[BuildingType.MetalMine] || 0
|
||||
if (metalMineLevel > 0) {
|
||||
metalProduction += Math.floor(
|
||||
METAL_MINE_PRODUCTION_BASE * metalMineLevel * Math.pow(METAL_MINE_PRODUCTION_FACTOR, metalMineLevel) * effectiveRatio
|
||||
)
|
||||
}
|
||||
metalProduction = Math.floor(metalProduction * (1 + bonuses.metalBonus))
|
||||
|
||||
// 晶体生产
|
||||
let crystalProduction = BASE_CRYSTAL_PRODUCTION
|
||||
const crystalMineLevel = planet.buildings[BuildingType.CrystalMine] || 0
|
||||
if (crystalMineLevel > 0) {
|
||||
crystalProduction += Math.floor(
|
||||
CRYSTAL_MINE_PRODUCTION_BASE * crystalMineLevel * Math.pow(CRYSTAL_MINE_PRODUCTION_FACTOR, crystalMineLevel) * effectiveRatio
|
||||
)
|
||||
}
|
||||
crystalProduction = Math.floor(crystalProduction * (1 + bonuses.crystalBonus))
|
||||
|
||||
// 重氢生产
|
||||
let deuteriumProduction = BASE_DEUTERIUM_PRODUCTION
|
||||
const deuteriumSynthesizerLevel = planet.buildings[BuildingType.DeuteriumSynthesizer] || 0
|
||||
if (deuteriumSynthesizerLevel > 0) {
|
||||
// 重氢生产受温度影响
|
||||
const tempModifier = planet.temperature ? 1.28 - 0.002 * planet.temperature.max : 1
|
||||
deuteriumProduction += Math.floor(
|
||||
DEUTERIUM_SYNTH_PRODUCTION_BASE *
|
||||
deuteriumSynthesizerLevel *
|
||||
Math.pow(DEUTERIUM_SYNTH_PRODUCTION_FACTOR, deuteriumSynthesizerLevel) *
|
||||
effectiveRatio *
|
||||
tempModifier
|
||||
)
|
||||
}
|
||||
|
||||
// 核聚变反应堆消耗重氢
|
||||
const fusionReactorLevel = planet.buildings[BuildingType.FusionReactor] || 0
|
||||
if (fusionReactorLevel > 0) {
|
||||
deuteriumProduction -= Math.floor(FUSION_DEUTERIUM_BASE * fusionReactorLevel * Math.pow(FUSION_DEUTERIUM_FACTOR, fusionReactorLevel))
|
||||
}
|
||||
|
||||
deuteriumProduction = Math.floor(deuteriumProduction * (1 + bonuses.deuteriumBonus))
|
||||
|
||||
return {
|
||||
metal: metalProduction,
|
||||
crystal: crystalProduction,
|
||||
deuterium: deuteriumProduction,
|
||||
darkMatter: 0,
|
||||
energy: 0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算存储容量(纯函数)
|
||||
* @pure
|
||||
*/
|
||||
export const calcStorageCapacity = (planet: Planet, storageCapacityBonus: number = 0): Resources => {
|
||||
const baseCapacity = BASE_STORAGE_CAPACITY
|
||||
const bonusMultiplier = 1 + storageCapacityBonus
|
||||
|
||||
// 金属仓库
|
||||
const metalStorageLevel = planet.buildings[BuildingType.MetalStorage] || 0
|
||||
const metalCapacity = Math.floor(baseCapacity * Math.pow(STORAGE_CAPACITY_FACTOR, metalStorageLevel) * bonusMultiplier)
|
||||
|
||||
// 晶体仓库
|
||||
const crystalStorageLevel = planet.buildings[BuildingType.CrystalStorage] || 0
|
||||
const crystalCapacity = Math.floor(baseCapacity * Math.pow(STORAGE_CAPACITY_FACTOR, crystalStorageLevel) * bonusMultiplier)
|
||||
|
||||
// 重氢储罐
|
||||
const deuteriumTankLevel = planet.buildings[BuildingType.DeuteriumTank] || 0
|
||||
const deuteriumCapacity = Math.floor(baseCapacity * Math.pow(STORAGE_CAPACITY_FACTOR, deuteriumTankLevel) * bonusMultiplier)
|
||||
|
||||
return {
|
||||
metal: metalCapacity,
|
||||
crystal: crystalCapacity,
|
||||
deuterium: deuteriumCapacity,
|
||||
darkMatter: Number.MAX_SAFE_INTEGER,
|
||||
energy: 0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算完整的生产数据(纯函数)
|
||||
* 这是主要的入口函数,聚合所有生产计算
|
||||
* @pure
|
||||
*/
|
||||
export const calcProduction = (planet: Planet, bonuses: ProductionBonuses, techBonuses?: TechBonuses): ProductionResult => {
|
||||
const energyProduction = calcEnergyProduction(planet, bonuses.energyProductionBonus)
|
||||
const energyConsumption = calcEnergyConsumption(planet)
|
||||
const energyRatio = energyConsumption > 0 ? Math.min(1, energyProduction / energyConsumption) : 1
|
||||
const capacity = calcStorageCapacity(planet, bonuses.storageCapacityBonus)
|
||||
|
||||
// 计算每秒生产量
|
||||
const productionPerSecond = calcResourceProduction(planet, energyRatio, techBonuses)
|
||||
|
||||
// 应用资源速度倍率
|
||||
const production: Resources = {
|
||||
metal: Math.floor(productionPerSecond.metal * bonuses.resourceSpeed),
|
||||
crystal: Math.floor(productionPerSecond.crystal * bonuses.resourceSpeed),
|
||||
deuterium: Math.floor(productionPerSecond.deuterium * bonuses.resourceSpeed),
|
||||
darkMatter: 0,
|
||||
energy: 0
|
||||
}
|
||||
|
||||
return {
|
||||
production,
|
||||
energyProduction,
|
||||
energyConsumption,
|
||||
energyRatio,
|
||||
capacity
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算时间段内的资源生产(纯函数)
|
||||
* @pure
|
||||
* @param planet 星球
|
||||
* @param deltaMs 时间间隔(毫秒)
|
||||
* @param bonuses 加成配置
|
||||
* @param techBonuses 科技加成
|
||||
* @returns 时间段内生产的资源量
|
||||
*/
|
||||
export const calcProductionForPeriod = (
|
||||
planet: Planet,
|
||||
deltaMs: number,
|
||||
bonuses: ProductionBonuses,
|
||||
techBonuses?: TechBonuses
|
||||
): Resources => {
|
||||
const productionData = calcProduction(planet, bonuses, techBonuses)
|
||||
const seconds = deltaMs / 1000
|
||||
|
||||
return {
|
||||
metal: Math.floor(productionData.production.metal * seconds),
|
||||
crystal: Math.floor(productionData.production.crystal * seconds),
|
||||
deuterium: Math.floor(productionData.production.deuterium * seconds),
|
||||
darkMatter: 0,
|
||||
energy: 0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用资源生产到星球(纯函数,返回新的资源状态)
|
||||
* @pure
|
||||
* @param currentResources 当前资源
|
||||
* @param produced 生产的资源
|
||||
* @param capacity 存储容量
|
||||
* @returns 新的资源状态和溢出量
|
||||
*/
|
||||
export const applyProduction = (
|
||||
currentResources: Resources,
|
||||
produced: Resources,
|
||||
capacity: Resources
|
||||
): { newResources: Resources; overflow: Resources } => {
|
||||
const newMetal = currentResources.metal + produced.metal
|
||||
const newCrystal = currentResources.crystal + produced.crystal
|
||||
const newDeuterium = currentResources.deuterium + produced.deuterium
|
||||
|
||||
const clampedMetal = Math.min(newMetal, capacity.metal)
|
||||
const clampedCrystal = Math.min(newCrystal, capacity.crystal)
|
||||
const clampedDeuterium = Math.min(newDeuterium, capacity.deuterium)
|
||||
|
||||
return {
|
||||
newResources: {
|
||||
metal: clampedMetal,
|
||||
crystal: clampedCrystal,
|
||||
deuterium: clampedDeuterium,
|
||||
darkMatter: currentResources.darkMatter + produced.darkMatter,
|
||||
energy: currentResources.energy
|
||||
},
|
||||
overflow: {
|
||||
metal: Math.max(0, newMetal - capacity.metal),
|
||||
crystal: Math.max(0, newCrystal - capacity.crystal),
|
||||
deuterium: Math.max(0, newDeuterium - capacity.deuterium),
|
||||
darkMatter: 0,
|
||||
energy: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user