|
|
| (не показано 185 промежуточных версий этого же участника) |
| Строка 1: |
Строка 1: |
| -- Загрузка данных
| |
| local latheData = mw.loadData("Модуль:IanComradeBot/prototypes/lathe.json/data") -- Функция для загрузки данных станков
| |
| local recipeData = mw.loadData("Модуль:IanComradeBot/prototypes/lathe/recipes.json/data") -- Функция для загрузки данных рецептов
| |
| local researchData = mw.loadData("Модуль:IanComradeBot/prototypes/research.json/data") -- Функция для загрузки данных исследований
| |
| local materialData = mw.loadData("Модуль:IanComradeBot/prototypes/materials.json/data") -- Функция для загрузки данных материалов
| |
| local chemData = mw.loadData("Модуль:IanComradeBot/chem prototypes.json/data") -- Функция для загрузки данных химических веществ
| |
|
| |
| local p = {} | | local p = {} |
|
| |
|
| -- Функция для форматирования времени | | -- Загрузка данных |
| local function format_seconds_to_short_string(input_seconds) | | local chemData = mw.loadData("Модуль:IanComradeBot/chem prototypes.json/data") |
| local minutes = math.floor(input_seconds / 60)
| | local seedsData = mw.loadData("Модуль:IanComradeBot/prototypes/seeds.json/data") |
| local seconds = input_seconds % 60
| |
|
| |
|
| local minutes_part = minutes > 0 and (minutes .. " мин.") or nil
| | local function kelvinToCelsius(k) |
| local seconds_part = seconds > 0 and (seconds .. " сек.") or nil
| | return k - 273.15 |
| | end |
|
| |
|
| if minutes_part and seconds_part then
| | local function findSeedById(id, data) |
| return minutes_part .. " " .. seconds_part
| | for _, seed in ipairs(data) do |
| elseif seconds_part then
| | if seed.id == id then |
| return seconds_part
| | return seed |
| elseif minutes_part then
| | end |
| return minutes_part
| | end |
| else
| | return nil |
| return '0 сек.'
| |
| end
| |
| end | | end |
|
| |
|
| -- Функция для сортировки рецептов
| | local function formatCharacteristics(seed) |
| local function sortRecipesByPriority(recipes) | | local parts = { |
| table.sort(recipes, function(a, b)
| | ("[[Гидропоника#Потенция|Потенция]]: %s"):format(seed.potency or 1), |
| local priority = { Static = 1, EMAG = 3 }
| | ("[[Гидропоника#Урожайность|Урожайность]]: %s"):format(seed.yield), |
| local aPriority = priority[a.discipline] or 2
| | ("[[Гидропоника#Срок жизни|Срок жизни]]: %s"):format(seed.lifespan), |
| local bPriority = priority[b.discipline] or 2
| | ("[[Гидропоника#Созревание|Созревание]]: %s"):format(seed.maturation), |
| | ("[[Гидропоника#Производство|Производство]]: %s"):format(seed.production), |
| | ("[[Гидропоника#Стадии роста|Стадии роста]]: %s"):format(seed.growthStages or 6), |
| | } |
| | return table.concat(parts, '<br>') |
| | end |
|
| |
|
| if a.isEmag ~= b.isEmag then
| | local function formatConditions(seed) |
| return not a.isEmag
| | local parts = { |
| end
| | ("[[Гидропоника#Потребление воды|Вода]]: %s"):format(seed.waterConsumption or 0.5), |
| | ("[[Гидропоника#Потребление нутриентов|Удобрение]]: %s"):format(seed.nutrientConsumption or 0.75), |
| | ("[[Гидропоника#Оптимальная температура|Темп.]]: %.2f°C"):format(kelvinToCelsius(seed.idealHeat or 293)), |
| | } |
| | return table.concat(parts, '<br>') |
| | end |
|
| |
|
| if aPriority == bPriority then
| | local function formatHarvestType(seed) |
| if a.tier == b.tier then
| | return seed.harvestRepeat and "[[Гидропоника#Тип урожая|" .. tostring(seed.harvestRepeat) .. "]]" or "-" |
| return a.discipline < b.discipline
| | end |
| end
| | local function formatHarvestType(seed) |
| return a.tier < b.tier
| | local harvestRepeat = seed.harvestRepeat |
| end
| | if harvestRepeat == "Repeat" then |
| | return "[[Гидропоника#Тип урожая|Многолетнее]]" |
| | elseif harvestRepeat == "SelfHarvest" then |
| | return "[[Гидропоника#Тип урожая|Самосбор]]" |
| | else |
| | return "[[Гидропоника#Тип урожая|Однолетнее]]" |
| | end |
| | end |
|
| |
|
| return aPriority < bPriority
| | local function formatChemicals(seed) |
| end)
| | if not seed.chemicals then return "-" end |
| | local list = {} |
| | for chemId, vals in pairs(seed.chemicals) do |
| | local entry = chemData[chemId] |
| | local chemName = entry and entry.name or chemId |
| | table.insert(list, string.format( |
| | "<li>[[Химия#chem_%s|%s]] (мин: %s, макс: %s, дел: %s)</li>", |
| | chemId, chemName, vals.Min or 0, vals.Max or 0, vals.PotencyDivisor or 1 |
| | )) |
| | end |
| | return "<ul>" .. table.concat(list) .. "</ul>" |
| end | | end |
|
| |
|
| function p.main(frame) | | local function formatMutations(seed, data) |
| -- Подключение CSS
| | if not seed.mutationPrototypes then return "-" end |
| local cssLink = frame:extensionTag('templatestyles', '', {
| | local list = {} |
| src = 'Шаблон:Prototypes/Машина/Станок/styles.css'
| | for _, mu in ipairs(seed.mutationPrototypes) do |
| })
| | local target = findSeedById(mu, data) |
| | if target and target.productPrototypes then |
| | for _, prod in ipairs(target.productPrototypes) do |
| | table.insert(list, ("<li>{{Предмет|%s|link=Гидропоника#{{#invoke:Entity Lookup|getname|%s}}}}</li>"):format(prod, prod)) |
| | end |
| | end |
| | end |
| | return "<ul>" .. table.concat(list) .. "</ul>" |
| | end |
|
| |
|
| local latheId = frame.args[1] or ""
| | local function generateHeader() |
| if latheId == "" then
| | return [[ |
| return '<div style="color:red;">Не указан ID станка.</div>'
| | {| id="BOTANY" class="wikitable sortable mw-collapsible" style="width:100%;" |
| end
| | ! rowspan="2" style="width:10%;" | Плод |
| | ! rowspan="2" class="unsortable" style="width:5%;" | Семена |
| | ! rowspan="2" class="unsortable" style="width:5%;" | Растение |
| | ! colspan="3" class="unsortable" style="width:30%;" id="no-highlight" | Характеристики |
| | ! rowspan="2" class="unsortable" style="width:30%;" | Содержит вещества |
| | ! rowspan="2" style="width:20%;" | Мутации |
| | |- |
| | ! style="width:10%;" class="unsortable" | Рост |
| | ! style="width:10%;" class="unsortable" | Условия |
| | ! style="width:5%;" class="unsortable" | Тип сбора |
| | ]] |
| | end |
|
| |
|
| local lathe = nil
| | local function generateFooter() |
| for _, data in ipairs(latheData) do
| | return "|}" |
| if data.id == latheId then
| | end |
| lathe = data
| |
| break
| |
| end
| |
| end
| |
|
| |
|
| if not lathe then
| | function p.table(frame) |
| return '<div style="color:red;">Станок с ID "' .. latheId .. '" не найден.</div>'
| | local data = mw.loadData("Модуль:IanComradeBot/prototypes/seeds.json/data") |
| end
| | local rows = {} |
|
| |
|
| if type(materialData) ~= "table" then
| | for _, seed in ipairs(data) do |
| return '<div style="color:red;">Ошибка: данные о материалах не загружены!</div>'
| | local prodId = seed.productPrototypes[1] |
| end
| | local seedId = seed.packetPrototype |
|
| | local seedName = string.format('{{#invoke:Entity Lookup|getname|%s}}', seedId) |
| local materialMapping = {}
| |
| for key, material in pairs(materialData) do
| |
| if type(material) == "table" and material.id then
| |
| materialMapping[material.id] = material.stackEntity or material.id
| |
| else
| |
| mw.log("Ошибка в materialData: " .. tostring(key) .. " -> " .. tostring(material))
| |
| end
| |
| end
| |
|
| |
|
| local chemMapping = {}
| | local anchor = string.format('{{anchor|%s}}', seedName) |
| for id, chem in pairs(chemData) do
| | local fruitImg = string.format( |
| chemMapping[id] = chem.name
| | '{{Предмет|%s|size=64px|vertical=1|imageTooltip=1|link=%s}}', |
| end
| | prodId, seedName |
| | ) |
| | local seedImg = string.format( |
| | '{{Предмет|%s|size=64px|vertical=1|imageTooltip=1|l=|link=%s}}', |
| | seedId, seedName |
| | ) |
| | local plantImg = string.format( |
| | '{{Предмет|%s-harvest|size=64px|l=|link=%s}}', |
| | seedId, seedName |
| | ) |
|
| |
|
| local out = cssLink
| | local colGrowth = formatCharacteristics(seed) |
| local recipes = {}
| | local colConditions = formatConditions(seed) |
| | local colHarvest = formatHarvestType(seed) |
| | local colChemicals = formatChemicals(seed) |
| | local colMutations = formatMutations(seed, data) |
|
| |
|
| local function getRecipeDetails(recipeId)
| | local row = frame:preprocess(string.format( |
| for _, recipe in ipairs(recipeData) do
| | [[|- |
| if recipe.id == recipeId then
| | ! %s |
| return recipe
| | ! %s |
| end
| | ! %s |
| end
| | | %s |
| return nil
| | | %s |
| end
| | | %s |
| | | %s |
| | | %s ]], |
| | fruitImg, seedImg, plantImg, |
| | colGrowth, colConditions, colHarvest, |
| | colChemicals, colMutations |
| | )) |
| | table.insert(rows, row) |
| | end |
|
| |
|
| local function findInResearch(recipeId)
| | return generateHeader() .. table.concat(rows, '\n') .. '\n' .. generateFooter() |
| for _, research in ipairs(researchData) do
| | end |
| if research.technology and research.technology.recipeUnlocks then
| |
| for _, unlock in ipairs(research.technology.recipeUnlocks) do
| |
| if unlock == recipeId then
| |
| return {
| |
| name = research.technology.name,
| |
| tier = research.technology.tier,
| |
| discipline = research.technology.discipline
| |
| }
| |
| end
| |
| end
| |
| end
| |
| end
| |
| return nil
| |
| end
| |
|
| |
|
| -- Обработка staticRecipes
| | function p.main(frame) |
| if lathe.Lathe.staticRecipes then
| | local args = frame.args |
| for _, recipeId in ipairs(lathe.Lathe.staticRecipes) do
| | local id = args[1] |
| local recipe = getRecipeDetails(recipeId)
| | local mode = mw.text.trim(args[2] or ""):lower() |
| if recipe and recipe.result then
| | local seed = findSeedById(id, seedsData) |
| table.insert(recipes, {
| | if not seed then return "" end |
| result = recipe.result,
| |
| completetime = recipe.completetime,
| |
| materials = recipe.materials,
| |
| discipline = "Static",
| |
| tier = 0
| |
| })
| |
| elseif recipe and recipe.resultReagents then
| |
| for reagent, amount in pairs(recipe.resultReagents) do
| |
| local reagentName = chemMapping[reagent] or reagent
| |
| table.insert(recipes, {
| |
| result = reagentName .. "|amount=" .. amount .. "ед.|mode-chem=1",
| |
| completetime = recipe.completetime,
| |
| materials = recipe.materials,
| |
| discipline = "Static",
| |
| tier = 0
| |
| })
| |
| break
| |
| end
| |
| else
| |
| out = out .. '<div style="color:red;">Ошибка: Рецепт с ID "' .. recipeId .. '" не найден или поля result/resultReagents отсутствуют.</div>'
| |
| end
| |
| end
| |
| end
| |
| | |
| -- Обработка dynamicRecipes
| |
| if lathe.Lathe.dynamicRecipes then
| |
| for _, recipeId in ipairs(lathe.Lathe.dynamicRecipes) do
| |
| local recipe = getRecipeDetails(recipeId)
| |
| if recipe then
| |
| local researchInfo = findInResearch(recipeId)
| |
| if researchInfo then
| |
| table.insert(recipes, {
| |
| result = recipe.result,
| |
| completetime = recipe.completetime,
| |
| materials = recipe.materials,
| |
| discipline = researchInfo.discipline,
| |
| tier = researchInfo.tier,
| |
| researchName = researchInfo.name
| |
| })
| |
| end
| |
| end
| |
| end
| |
| end
| |
| | |
| -- Обработка emagStaticRecipes
| |
| if lathe.EmagLatheRecipes and lathe.EmagLatheRecipes.emagStaticRecipes then
| |
| for _, recipeId in ipairs(lathe.EmagLatheRecipes.emagStaticRecipes) do
| |
| local recipe = getRecipeDetails(recipeId)
| |
| if recipe then
| |
| table.insert(recipes, {
| |
| result = recipe.result,
| |
| completetime = recipe.completetime,
| |
| materials = recipe.materials,
| |
| discipline = "Static",
| |
| tier = 0,
| |
| isEmag = true
| |
| })
| |
| end
| |
| end
| |
| end
| |
| | |
| -- Обработка emagDynamicRecipes
| |
| if lathe.EmagLatheRecipes and lathe.EmagLatheRecipes.emagDynamicRecipes then
| |
| for _, recipeId in ipairs(lathe.EmagLatheRecipes.emagDynamicRecipes) do
| |
| local recipe = getRecipeDetails(recipeId)
| |
| if recipe then
| |
| local researchInfo = findInResearch(recipeId)
| |
| if researchInfo then
| |
| table.insert(recipes, {
| |
| result = recipe.result,
| |
| completetime = recipe.completetime,
| |
| materials = recipe.materials,
| |
| discipline = researchInfo.discipline,
| |
| tier = researchInfo.tier,
| |
| researchName = researchInfo.name,
| |
| isEmag = true
| |
| })
| |
| end
| |
| end
| |
| end
| |
| end
| |
| | |
| sortRecipesByPriority(recipes)
| |
| | |
| -- Таблица для перевода названий дисциплин
| |
| local disciplineMapping = {
| |
| Arsenal = "Арсенал",
| |
| Industrial = "Промышленность",
| |
| Experimental = "Экспериментальное",
| |
| CivilianServices = "Обслуживание персонала"
| |
| }
| |
| | |
| -- Таблица для цветов по уровням
| |
| local tierColors = {
| |
| [1] = "#54d554",
| |
| [2] = "#ed9000",
| |
| [3] = "#d72a2a"
| |
| }
| |
| | |
| local materialUseMultiplier = lathe.Lathe.materialUseMultiplier or 1
| |
| local timeMultiplier = lathe.Lathe.timeMultiplier or 1
| |
| | |
| for _, recipe in ipairs(recipes) do
| |
| local scaledTime = format_seconds_to_short_string(recipe.completetime * timeMultiplier)
| |
| out = out .. '{{Шаблон:Prototypes/Машина/Станок|product=' .. recipe.result
| |
| out = out .. '|complete-time=' .. scaledTime
| |
| out = out .. '|materials='
| |
| | |
| if next(recipe.materials) then
| |
| for material, amount in pairs(recipe.materials) do
| |
| local stackEntity = materialMapping[material] or material
| |
| local scaledAmount = (amount * materialUseMultiplier) / 100
| |
| out = out .. '<b>[[File:' .. stackEntity .. '.png|32x32px|link=]] ' .. scaledAmount .. ' {{#invoke:Entity Lookup|getname|' .. stackEntity .. '}}</b>'
| |
| end
| |
| else
| |
| out = out .. 'Нет данных о материалах'
| |
| end
| |
| | |
| -- Информация об исследовании
| |
| if recipe.discipline ~= "Static" then
| |
| local tierColor = tierColors[recipe.tier] or "#FFFFFF"
| |
| local disciplineName = disciplineMapping[recipe.discipline] or "Неизвестная дисциплина"
| |
| | |
| out = out .. '|info=<div style="font-weight:600;"><span style="margin:8px;">[[File:' .. recipe.discipline .. '.png|16x16px|link=]]</span> [[Руководство по исследованию и разработке|' .. disciplineName
| |
| out = out .. ']], уровень: <span style="color: ' .. tierColor .. '">' .. recipe.tier .. '</span> </div>'
| |
| end
| |
| | |
| -- Пометка при взломе EMAG
| |
| if recipe.isEmag then
| |
| out = out .. '|mode-emag=1'
| |
| end
| |
| | |
| -- Пометка для исследуемой технологии
| |
| if recipe.discipline ~= "Static" then
| |
| out = out .. '|mode-research=1'
| |
| end
| |
| | |
| out = out .. '}}'
| |
| end
| |
|
| |
|
| return mw.getCurrentFrame():preprocess(out)
| | if mode == "growth" then |
| | return formatCharacteristics(seed) |
| | elseif mode == "conditions" then |
| | return formatConditions(seed) |
| | elseif mode == "harvest" then |
| | return formatHarvestType(seed) |
| | elseif mode == "chemicals" then |
| | return formatChemicals(seed) |
| | elseif mode == "mutations" then |
| | return formatMutations(seed, seedsData) |
| | else |
| | return "" |
| | end |
| end | | end |
|
| |
|
| return p | | return p |