全站通知:
模块:Crop Growth Calendars
刷
历
编
跳到导航
跳到搜索
local cache = require "mw.ext.LuaCache"
local KEY_PREFIX = "Crop Growth Calendars"
local EXP_TIME = 172800
local p = {}
local private = {}
local Helper = require("Module:Helper")
local ID = require("Module:ID")
local Name = require("Module:Name")
local data = Helper.LazyLoad('Module:Crops/data')
----------main function----------
function p.calendar(frame)
-- input args
local rawArgs = frame.args
local args = {}
for k, v in pairs(rawArgs) do
if type(v) == 'string' and not v:match('%S') then
v = nil
end
args[k] = v
end
local name = args.name
local cacheKey = KEY_PREFIX .. name
if (cache.get(cacheKey)) then
local result = cache.get(cacheKey)
return result
end
local size = tonumber(args.size) or 36
local speedIncrease = tonumber(args.increase) or 0
local season = args.season
local irrigation = args.irrigation
local mode = args.mode
local title = args.title
local stageImage = args.image1 or (name and (name .. ' Stage') or nil)
local cropImage = args.image2 or name
----------Dictionary----------
Dictionary = {
['speedGro'] = '[[生长激素]]',
['deluxeSpeedGro'] = '[[高级生长激素]]',
['hyperSpeedGro'] = '[[顶级生长激素]]',
['agriculturist'] = '农业学家',
['monday'] = '一',
['tuesday'] = '二',
['wednesday'] = '三',
['thursday'] = '四',
['friday'] = '五',
['saturday'] = '六',
['sunday'] = '日',
['spring'] = '春季',
['summer'] = '夏季',
['fall'] = '秋季',
['winter'] = '冬季',
['collapsibleTable1'] = '[[耕种#耕种技能|农业学家]]和生长激素的对比',
['collapsibleTable1Unirrigated'] = '农业学家和生长激素的对比 - 普通',
['collapsibleTable2Irrigated'] = '农业学家和生长激素的对比 - 临近水域',
['regular'] = '无职业加成',
['note'] = '提示:职业为[[技能#耕种|农业学家]]并且没有使用任何肥料时,生长日历与此表格一致。',
['dayOne'] = ' 1 日',
['base'] = '无任何加成',
['irrigated'] = ' - 临近水域',
['unirrigated'] = ' - 普通',
['ifPlantOn'] = '(如果在',
['closeParen'] = '种植)'
}
----------crops' data----------
-- Get crop data from new format
local id = ID.id {args = {name}}
if id:sub(1, 3) == "(O)" then id = id:sub(4) end
-- Find crop seed ID by HarvestItemId
local seedId = nil
for cropKey, cropInfo in pairs(data) do
if cropInfo['HarvestItemId'] == id then
seedId = cropKey
break
end
end
local eng = Name.reverse_name {args = {name}}
if eng ~= '' then
name = eng
stageImage = args.image1 or (name and (name .. ' Stage') or nil)
cropImage = args.image2 or name
end
-- Use the found seed ID or fall back to original name
local cropLookupKey = seedId or name
local cropData = data[cropLookupKey]
if not cropData then
error("Crop data not found for harvest item ID: " .. id ..
" (original name: " .. name .. ")")
end
local phaseDays = cropData['DaysInPhase']
if not season then
-- Convert seasons to lowercase for compatibility
season = {}
for i, s in ipairs(cropData['Seasons']) do
season[i] = string.lower(s)
end
else
season = mw.text.split(season, " ")
end
local regrowth = cropData['RegrowDays']
-- When mode = 'base', only return base wikitable
if mode == 'base' then
return p.month(name, size, phaseDays, regrowth, speedIncrease, season,
'', stageImage, cropImage, title)
end
----------cropCalendars begin (irrigation='yes')----------
local cropCalendars = ''
-- whether the crop can be irrigated or not
if irrigation == 'yes' then
-- Base form
cropCalendars = cropCalendars .. '<table><tr><td>' ..
p.month(name, '', phaseDays, regrowth, 0, season,
'no', stageImage, cropImage) .. '</td><td>' ..
p.month(name, '', phaseDays, regrowth, 0, season,
'yes', stageImage, cropImage) ..
'</td></tr></table>' ..
-- Agriculturist and Speed-Gro Comparison - Unirrigated
'<table class=\"wikitable roundedborder mw-collapsible mw-collapsed\" style="text-align:center;\">' ..
'<tr><th colspan=\"4\" style=\"min-width:450px; min-height:40px;\">' ..
Dictionary['collapsibleTable1Unirrigated'] ..
'</th></tr>' .. '<tr>' ..
'<th></th><th>[[File:Speed-Gro.png|24px|link=]] ' ..
Dictionary['speedGro'] .. '</th>' ..
'<th>[[File:Deluxe Speed-Gro.png|24px|link=]] ' ..
Dictionary['deluxeSpeedGro'] .. '</th>' ..
'<th>[[File:Hyper Speed-Gro.png|24px|link=]] ' ..
Dictionary['hyperSpeedGro'] .. '</th>' ..
'</tr><tr>' ..
'<th rowspan=\"2\" style=\"max-width: 2em; padding: 0;\"><div>' ..
Dictionary['regular'] .. '</div></th>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\">' ..
p.month(name, size, phaseDays, regrowth, 0.1,
season, 'no', stageImage, cropImage) ..
'</td>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\">' ..
p.month(name, size, phaseDays, regrowth, 0.25,
season, 'no', stageImage, cropImage) ..
'</td>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\">' ..
p.month(name, size, phaseDays, regrowth, 0.33,
season, 'no', stageImage, cropImage) ..
'</td>' .. '</tr>' .. '<tr>' ..
'<td colspan=\"3\" style=\"background-color: transparent; padding: 0 0 0 8px; text-align: left; font-size: smaller; border: 0;\">*' ..
Dictionary['note'] .. '</td>' .. '</tr>' .. '<tr>' ..
'<th style=\"max-width: 2em; padding: 0;\"><div>[[File:Agriculturist.png|24px|link=]] ' ..
Dictionary['agriculturist'] .. '</div></th>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\">' ..
p.month(name, size, phaseDays, regrowth, 0.2,
season, 'no', stageImage, cropImage) ..
'</td>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\">' ..
p.month(name, size, phaseDays, regrowth, 0.35,
season, 'no', stageImage, cropImage) ..
'</td>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\"|>' ..
p.month(name, size, phaseDays, regrowth, 0.43,
season, 'no', stageImage, cropImage) ..
'</td>' .. '</tr></table>' ..
-- Agriculturist and Speed-Gro Comparison - Irrigated
'<table class=\"wikitable roundedborder mw-collapsible mw-collapsed\" style="text-align:center;\">' ..
'<tr><th colspan=\"4\" style=\"min-width:450px; min-height:40px;\">' ..
Dictionary['collapsibleTable2Irrigated'] ..
'</th></tr>' .. '<tr>' ..
'<th></th><th>[[File:Speed-Gro.png|24px|link=]] ' ..
Dictionary['speedGro'] .. '</th>' ..
'<th>[[File:Deluxe Speed-Gro.png|24px|link=]] ' ..
Dictionary['deluxeSpeedGro'] .. '</th>' ..
'<th>[[File:Hyper Speed-Gro.png|24px|link=]] ' ..
Dictionary['hyperSpeedGro'] .. '</th>' ..
'</tr><tr>' ..
'<th rowspan=\"2\" style=\"max-width: 2em; padding: 0;\"><div>' ..
Dictionary['regular'] .. '</div></th>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\">' ..
p.month(name, size, phaseDays, regrowth, 0.1,
season, 'yes', stageImage, cropImage) ..
'</td>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\">' ..
p.month(name, size, phaseDays, regrowth, 0.25,
season, 'yes', stageImage, cropImage) ..
'</td>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\">' ..
p.month(name, size, phaseDays, regrowth, 0.33,
season, 'yes', stageImage, cropImage) ..
'</td>' .. '</tr>' .. '<tr>' ..
'<td colspan=\"3\" style=\"background-color: transparent; padding: 0 0 0 8px; text-align: left; font-size: smaller; border: 0;\">*' ..
Dictionary['note'] .. '</td>' .. '</tr>' .. '<tr>' ..
'<th style=\"max-width: 2em; padding: 0;\"><div>[[File:Agriculturist.png|24px|link=]] ' ..
Dictionary['agriculturist'] .. '</div></th>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\">' ..
p.month(name, size, phaseDays, regrowth, 0.2,
season, 'yes', stageImage, cropImage) ..
'</td>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\">' ..
p.month(name, size, phaseDays, regrowth, 0.35,
season, 'yes', stageImage, cropImage) ..
'</td>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\"|>' ..
p.month(name, size, phaseDays, regrowth, 0.43,
season, 'yes', stageImage, cropImage) ..
'</td>' .. '</tr></table>'
----------cropCalendars begin (irrigation=default)----------
-- Base form
else
cropCalendars = cropCalendars ..
p.month(name, '', phaseDays, regrowth, 0, season,
'', stageImage, cropImage) ..
'<table class=\"wikitable roundedborder mw-collapsible mw-collapsed\" style="text-align:center;\">' ..
'<tr><th colspan=\"4\" style=\"min-width:450px; min-height:40px;\">' ..
Dictionary['collapsibleTable1'] .. '</th></tr>' ..
'<tr>' ..
'<th></th><th>[[File:Speed-Gro.png|24px|link=]] ' ..
Dictionary['speedGro'] .. '</th>' ..
'<th>[[File:Deluxe Speed-Gro.png|24px|link=]] ' ..
Dictionary['deluxeSpeedGro'] .. '</th>' ..
'<th>[[File:Hyper Speed-Gro.png|24px|link=]] ' ..
Dictionary['hyperSpeedGro'] .. '</th>' ..
'</tr><tr>' ..
'<th rowspan=\"2\" style=\"max-width: 2em; padding: 0;\"><div>' ..
Dictionary['regular'] .. '</div></th>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\">' ..
p.month(name, size, phaseDays, regrowth, 0.1,
season, '', stageImage, cropImage) ..
'</td>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\">' ..
p.month(name, size, phaseDays, regrowth, 0.25,
season, '', stageImage, cropImage) ..
'</td>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\">' ..
p.month(name, size, phaseDays, regrowth, 0.33,
season, '', stageImage, cropImage) ..
'</td>' .. '</tr>' .. '<tr>' ..
'<td colspan=\"3\" style=\"background-color: transparent; padding: 0 0 0 8px; text-align: left; font-size: smaller; border: 0;\">*' ..
Dictionary['note'] .. '</td>' .. '</tr>' .. '<tr>' ..
'<th style=\"max-width: 2em; padding: 0;\"><div>[[File:Agriculturist.png|24px|link=]] ' ..
Dictionary['agriculturist'] .. '</div></th>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\">' ..
p.month(name, size, phaseDays, regrowth, 0.2,
season, '', stageImage, cropImage) ..
'</td>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\">' ..
p.month(name, size, phaseDays, regrowth, 0.35,
season, '', stageImage, cropImage) ..
'</td>' ..
'<td style=\"background-color: transparent; border: 0; vertical-align: top;\"|>' ..
p.month(name, size, phaseDays, regrowth, 0.43,
season, '', stageImage, cropImage) ..
'</td>' .. '</tr></table>'
end
----------cropCalendars end----------
cache.set(cacheKey, cropCalendars)
return cropCalendars
end
----------return given crop's calendar (only one table each time)----------
function p.month(name, size, phaseDays, regrowth, speedIncrease, season,
irrigation, stageImage, cropImage, ...)
local phaseDays = private.copy(phaseDays)
local season = private.copy(season)
-- whether input title
local title = ''
if ... then title = ... end
-- define sizeString used in image, e.g. sizeString = '|36px'
-- define cellWidth used in wikitable
local sizeString = ''
local cellWidth = '48px'
if size ~= '' then
sizeString = '|' .. size .. 'px'
cellWidth = size .. 'px'
end
local totalDaysOfCropGrowth = 0
-- only support 2 seasons because of layout. Display 1 season when crop can't regrow.
if #season > 2 or regrowth == -1 then season = season[1] end
-- speedIncrease + 0.25 when irragated
speedIncreaseInitial = speedIncrease
if irrigation == 'yes' then speedIncrease = speedIncrease + 0.25 end
-- calculate total days of crop growth (phaseDays is already a number array)
for i = 1, #phaseDays, 1 do
totalDaysOfCropGrowth = totalDaysOfCropGrowth + phaseDays[i]
end
local daysToRemove = math.ceil(totalDaysOfCropGrowth * speedIncrease)
-- Unexpected result in C# when using floating-point arithmetic, see Talk:Crop Growth Calendars
-- Only consider totalDaysOfCropGrowth <=28 and (speedIncrease = 0.1,0.2,0.25,0.35,0.45,0.5,0.6, 0.33,0.43,0.68)
if speedIncrease == 0.1 then
for key, value in pairs {10, 20} do
if totalDaysOfCropGrowth == value then
daysToRemove = daysToRemove + 1
break
end
end
elseif speedIncrease == 0.2 then
for key, value in pairs {5, 10, 15, 20, 25} do
if totalDaysOfCropGrowth == value then
daysToRemove = daysToRemove + 1
break
end
end
elseif speedIncrease == 0.6 then
for key, value in pairs {5, 10, 15, 20, 25} do
if totalDaysOfCropGrowth == value then
daysToRemove = daysToRemove + 1
break
end
end
end
-- calculate phaseDays after speedIncrease
local tries = 0
-- special:misnamed crop images, e.g. Green Bean, Hops.
-- Delete the 0 cell before removing and add them back after removing
local phaseZero = 0
for i = 1, #phaseDays, 1 do
if phaseDays[i] == 0 then
phaseZero = i
table.remove(phaseDays, i)
break
end
end
-- Calculate. ConcernApe's C# code doesn't consider phaseDay[i] = 0.
-- So the following code doesn't consider this situation, too.
-- e.g. phaseDays = {1,1,2,3,3} (Grape), speedIncrease = 0.43.
-- After removing, it becomes {1,-1,1,2,2}. Totalday is 1+1+2+2=6. And actually it is 6 days in the game.
-- However, if speedIncrease = 0.43, it should be 5 days {1,0,0,2,2}
while daysToRemove > 0 and tries < 3 do
for i = 1, #phaseDays, 1 do
if i > 1 or phaseDays[i] > 1 then
phaseDays[i] = phaseDays[i] - 1
daysToRemove = daysToRemove - 1
end
if daysToRemove <= 0 then break end
end
tries = tries + 1
end
-- Add back
if phaseZero ~= 0 then table.insert(phaseDays, phaseZero, 0) end
-- 2-month days picture
local picList = {}
local daysLeft = 56
local circulateOrNot = ''
while daysLeft > 0 do
-- Crops which are reseeded should skip Day 1
if daysLeft < 56 and circulateOrNot ~= 'yes' then
phaseDays[1] = phaseDays[1] - 1
circulateOrNot = 'yes'
end
for stage = 1, #phaseDays, 1 do
for stageDay = 1, phaseDays[stage], 1 do
-- special: File:Hot_Pepper_Stage_4b.png
if name == 'Hot Pepper' and stage == 5 then
table.insert(picList,
'[[File:' .. stageImage .. ' 4b.png' ..
sizeString .. '|center|link=]]')
else
table.insert(picList,
'[[File:' .. stageImage .. ' ' .. stage ..
'.png' .. sizeString .. '|center|link=]]')
end
daysLeft = daysLeft - 1
if daysLeft == 0 then break end
end
if daysLeft == 0 then break end
end
if daysLeft == 0 then break end
table.insert(picList, '[[File:' .. cropImage .. '.png' .. sizeString ..
'|center|link=]]')
daysLeft = daysLeft - 1
if daysLeft == 0 then break end
if regrowth ~= -1 then
local stageRegrowth = #phaseDays + 2
while daysLeft > 0 do
for regrowthDays = 1, regrowth - 1, 1 do
-- special: File:Hot_Pepper_Stage_6.png
if name == 'Hot Pepper' then
table.insert(picList, '[[File:' .. stageImage ..
' 6.png' .. sizeString ..
'|center|link=]]')
else
table.insert(picList,
'[[File:' .. stageImage .. ' ' ..
stageRegrowth .. '.png' .. sizeString ..
'|center|link=]]')
end
daysLeft = daysLeft - 1
if daysLeft == 0 then break end
end
if daysLeft == 0 then break end
table.insert(picList, '[[File:' .. cropImage .. '.png' ..
sizeString .. '|center|link=]]')
daysLeft = daysLeft - 1
end
end
end
-- table title relating to speedIncrease (10% and 0% are special)
if title == '' then
if speedIncreaseInitial == 0.1 or speedIncreaseInitial == 0 then
if speedIncreaseInitial == 0 then
title = title .. Dictionary['base']
else
title = '10%*'
end
else
title = tostring(speedIncreaseInitial * 100) .. '%'
end
end
-- irrigation
if irrigation == 'yes' then title = title .. Dictionary['irrigated'] end
if irrigation == 'no' then title = title .. Dictionary['unirrigated'] end
-- wikitable's header row
local wikitableTitle = '' ..
'<table class=\"wikitable roundedborder\" style="text-align:center;\">' ..
'<tr>' .. '<th colspan=\"7\">' .. title ..
'</th>' .. '</tr>'
-- calendar season 1
local wikitable1 = '' .. '<tr>' .. '<th style=\"width: ' .. cellWidth ..
';\">' .. Dictionary['monday'] .. '</th>' ..
'<th style=\"width: ' .. cellWidth .. ';\">' ..
Dictionary['tuesday'] .. '</th>' ..
'<th style=\"width: ' .. cellWidth .. ';\">' ..
Dictionary['wednesday'] .. '</th>' ..
'<th style=\"width: ' .. cellWidth .. ';\">' ..
Dictionary['thursday'] .. '</th>' ..
'<th style=\"width: ' .. cellWidth .. ';\">' ..
Dictionary['friday'] .. '</th>' ..
'<th style=\"width: ' .. cellWidth .. ';\">' ..
Dictionary['saturday'] .. '</th>' ..
'<th style=\"width: ' .. cellWidth .. ';\">' ..
Dictionary['sunday'] .. '</th>'
-- crops images
for i = 1, 28, 1 do
-- another row
if math.fmod(i, 7) == 1 then
wikitable1 = wikitable1 .. '</tr><tr>'
end
wikitable1 = wikitable1 .. '<td>' .. picList[i] .. '</td>'
end
wikitable1 = wikitable1 .. '</tr>'
local wikitable2 = ''
-- special:calendar season 2
if #season == 2 then
wikitable2 =
wikitable2 .. '<tr>' .. '<th style=\"width: ' .. cellWidth .. ';\">' ..
Dictionary['monday'] .. '</th>' .. '<th style=\"width: ' ..
cellWidth .. ';\">' .. Dictionary['tuesday'] .. '</th>' ..
'<th style=\"width: ' .. cellWidth .. ';\">' ..
Dictionary['wednesday'] .. '</th>' .. '<th style=\"width: ' ..
cellWidth .. ';\">' .. Dictionary['thursday'] .. '</th>' ..
'<th style=\"width: ' .. cellWidth .. ';\">' ..
Dictionary['friday'] .. '</th>' .. '<th style=\"width: ' ..
cellWidth .. ';\">' .. Dictionary['saturday'] .. '</th>' ..
'<th style=\"width: ' .. cellWidth .. ';\">' ..
Dictionary['sunday'] .. '</th>'
-- crops images
for i = 29, 56, 1 do
-- another row
if math.fmod(i, 7) == 1 then
wikitable2 = wikitable2 .. '</tr><tr>'
end
wikitable2 = wikitable2 .. '<td>' .. picList[i] .. '</td>'
end
wikitable2 = wikitable2 .. '</tr>'
end
local wikitable = ''
-- 1 or 2 tables to output
if #season == 2 then
-- horizontal or vertical tables
if speedIncrease == 0 then
local wikitableTitle2 = '' ..
'<table class=\"wikitable roundedborder\" style="text-align:center;\">' ..
'<tr>' .. '<th colspan=\"7\">' ..
Dictionary['base'] .. ' - ' ..
Dictionary[season[2]] ..
Dictionary['ifPlantOn'] ..
Dictionary[season[1]] ..
Dictionary['dayOne'] ..
Dictionary['closeParen'] .. '</th>' ..
'</tr>'
wikitable = wikitable .. '<table><tr><td>' .. wikitableTitle ..
wikitable1 .. '</table></td><td>' .. wikitableTitle2 ..
wikitable2 .. '</table></td></tr></table>'
else
wikitable = wikitable .. wikitableTitle .. '<tr>' ..
'<th colspan=\"7\">' .. Dictionary[season[1]] ..
'</th>' .. '</tr>' .. wikitable1 .. '<tr>' ..
'<th colspan=\"7\">' .. Dictionary[season[2]] ..
'</th>' .. '</tr>' .. wikitable2 .. '</table>'
end
else
wikitable = wikitable .. wikitableTitle .. wikitable1 .. '</table>'
end
return wikitable
end
----------clone tables----------
function private.copy(t)
local t2 = {}
for k, v in pairs(t) do t2[k] = v end
return t2
end
return p