- Welcome to the Kancolle Wiki!
- If you have any questions regarding site content, account registration, etc., please visit the KanColle Wiki Discord
Difference between revisions of "Module:Iterator"
Jump to navigation
Jump to search
(some enemy iterator) |
|||
Line 2: | Line 2: | ||
-- more generic interface and compositions (filtering, grouping, mapping, sorting, etc.) | -- more generic interface and compositions (filtering, grouping, mapping, sorting, etc.) | ||
-- prevent clients from infinite loops | -- prevent clients from infinite loops | ||
+ | -- load modules more lazily? | ||
+ | -- generalize equipment/enemy iterators | ||
local U = require('Module:Utils') | local U = require('Module:Utils') | ||
local EquipmentData = require('Module:EquipmentData') | local EquipmentData = require('Module:EquipmentData') | ||
local CollectionEquipment = require('Module:Collection/Equipment') | local CollectionEquipment = require('Module:Collection/Equipment') | ||
+ | local EnemyShip = require('Module:EnemyShip') | ||
+ | local CollectionEnemy = require('Module:Collection/EnemyShips') | ||
local Iterator = {} | local Iterator = {} | ||
Line 31: | Line 35: | ||
return context and tonumber(context[name .. (n and tostring(n) or '')]) or default | return context and tonumber(context[name .. (n and tostring(n) or '')]) or default | ||
end | end | ||
+ | |||
+ | -- * Equipment iterators. | ||
function Iterator.equipmentBy(context, n, pred, pre) | function Iterator.equipmentBy(context, n, pred, pre) | ||
Line 127: | Line 133: | ||
end) | end) | ||
end | end | ||
+ | |||
+ | -- * Enemy iterators. | ||
+ | |||
+ | function Iterator.enemiesByType(context, n) | ||
+ | local collection = U.imap(CollectionEnemy, function(name) | ||
+ | return EnemyShip(name) | ||
+ | end) | ||
+ | table.sort(collection, function(a, b) | ||
+ | local ai = U.ifind(CollectionEnemy, a:base_name()) | ||
+ | local bi = U.ifind(CollectionEnemy, b:base_name()) | ||
+ | if ai and bi and ai ~= bi then | ||
+ | return ai < bi | ||
+ | else | ||
+ | return a._id < b._id | ||
+ | end | ||
+ | end) | ||
+ | local type = numberKey('type', context, n) | ||
+ | local pred = function(e, i) | ||
+ | return e:type() == type | ||
+ | end | ||
+ | local pre | ||
+ | local i = 1 | ||
+ | local current = nil | ||
+ | local preFlag = true | ||
+ | return { | ||
+ | next = function() | ||
+ | for _ = i, #collection do | ||
+ | local e = collection[i] | ||
+ | if pred(e, i) then | ||
+ | if pre and preFlag then | ||
+ | local value = pre(e, i) | ||
+ | if value then | ||
+ | current = value | ||
+ | preFlag = false | ||
+ | return true | ||
+ | end | ||
+ | end | ||
+ | current = e:lua_name() | ||
+ | i = i + 1 | ||
+ | preFlag = true | ||
+ | return true | ||
+ | end | ||
+ | i = i + 1 | ||
+ | end | ||
+ | current = nil | ||
+ | return false | ||
+ | end, | ||
+ | current = function() | ||
+ | return current | ||
+ | end, | ||
+ | } | ||
+ | end | ||
+ | |||
+ | -- * Tests. | ||
function Iterator.test() | function Iterator.test() | ||
Line 133: | Line 193: | ||
mw.log(name) | mw.log(name) | ||
while iterator.next() do | while iterator.next() do | ||
− | mw.log(' ' .. iterator.current()) | + | mw.log(' ' .. (iterator.current() or '?')) |
end | end | ||
mw.log() | mw.log() | ||
Line 143: | Line 203: | ||
testIterator('equipmentByTypeAndIcon', { type = '1', icon = '16' }) | testIterator('equipmentByTypeAndIcon', { type = '1', icon = '16' }) | ||
testIterator('equipmentBy', { pred = 'is_large_caliber_main_gun', sort = '_type' }) | testIterator('equipmentBy', { pred = 'is_large_caliber_main_gun', sort = '_type' }) | ||
+ | testIterator('enemiesByType', { type = '2' }) | ||
end | end | ||
-- p.test() | -- p.test() | ||
return Iterator | return Iterator |
Revision as of 17:46, 28 March 2018
Documentation for this module may be created at Module:Iterator/doc
-- [[Category:Todo]]:
-- more generic interface and compositions (filtering, grouping, mapping, sorting, etc.)
-- prevent clients from infinite loops
-- load modules more lazily?
-- generalize equipment/enemy iterators
local U = require('Module:Utils')
local EquipmentData = require('Module:EquipmentData')
local CollectionEquipment = require('Module:Collection/Equipment')
local EnemyShip = require('Module:EnemyShip')
local CollectionEnemy = require('Module:Collection/EnemyShips')
local Iterator = {}
-- legacy, not a proper iterator
function Iterator.array(arr, i, n)
i = i or 0
n = n and math.min(#arr, n) or #arr
function step(n, i)
if i < n then
i = i + 1
return i, arr[i]
end
end
return function()
return step, n, i
end
end
function stringKey(name, context, n, default)
return context and context[name .. (n and tostring(n) or '')] or default
end
function numberKey(name, context, n, default)
return context and tonumber(context[name .. (n and tostring(n) or '')]) or default
end
-- * Equipment iterators.
function Iterator.equipmentBy(context, n, pred, pre)
local predKey = stringKey('pred', context, n)
if predKey then
pred = function(e)
local obj = EquipmentData(e)
return obj[predKey](obj)
end
end
local collection = U.icopy(CollectionEquipment)
local sortKey = stringKey('sort', context, n)
if sortKey then
table.sort(collection, function(a, b)
if a[sortKey] ~= b[sortKey] then
return a[sortKey] < b[sortKey]
else
return a._id < b._id
end
end)
end
local i = 1
local current = nil
local preFlag = true
return {
next = function()
for _ = i, #collection do
local e = collection[i]
if pred(e, i) then
if pre and preFlag then
local value = pre(e, i)
if value then
current = value
preFlag = false
return true
end
end
current = e._name
i = i + 1
preFlag = true
return true
end
i = i + 1
end
current = nil
return false
end,
current = function()
return current
end,
}
end
function Iterator.equipmentById(context, n)
local from = numberKey('from', context, n, 1)
local to = numberKey('to', context, n, 500)
return Iterator.equipmentBy(context, n, function(e)
return e._id >= from and e._id <= to
end)
end
function Iterator.equipmentByIdWithHeaders(context, n)
local from = numberKey('from', context, n, 1)
local to = numberKey('to', context, n, 500)
local prevMod = 0
return Iterator.equipmentBy(
context, n,
function(e)
return e._id >= from and e._id <= to
end,
function(e)
local currentMod = (e._id - 1) % 10
if currentMod <= prevMod then
prevMod = currentMod
return "!#No " .. U.pad(e._id - currentMod, 3, "0") .. " - " .. U.pad(e._id - currentMod + 9, 3, "0")
else
prevMod = currentMod
return false
end
end
)
end
function Iterator.equipmentByType(context, n)
local type = numberKey('type', context, n)
return Iterator.equipmentBy(context, n, function(e)
return e._type == type
end)
end
function Iterator.equipmentByTypeAndIcon(context, n)
local type = numberKey('type', context, n)
local icon = numberKey('icon', context, n)
return Iterator.equipmentBy(context, n, function(e)
return e._type == type and e._icon == icon
end)
end
-- * Enemy iterators.
function Iterator.enemiesByType(context, n)
local collection = U.imap(CollectionEnemy, function(name)
return EnemyShip(name)
end)
table.sort(collection, function(a, b)
local ai = U.ifind(CollectionEnemy, a:base_name())
local bi = U.ifind(CollectionEnemy, b:base_name())
if ai and bi and ai ~= bi then
return ai < bi
else
return a._id < b._id
end
end)
local type = numberKey('type', context, n)
local pred = function(e, i)
return e:type() == type
end
local pre
local i = 1
local current = nil
local preFlag = true
return {
next = function()
for _ = i, #collection do
local e = collection[i]
if pred(e, i) then
if pre and preFlag then
local value = pre(e, i)
if value then
current = value
preFlag = false
return true
end
end
current = e:lua_name()
i = i + 1
preFlag = true
return true
end
i = i + 1
end
current = nil
return false
end,
current = function()
return current
end,
}
end
-- * Tests.
function Iterator.test()
function testIterator(name, args)
local iterator = Iterator[name](args)
mw.log(name)
while iterator.next() do
mw.log(' ' .. (iterator.current() or '?'))
end
mw.log()
end
testIterator('equipmentById', { from = '11', to = '20' })
testIterator('equipmentByIdWithHeaders', { from = '1', to = '30' })
testIterator('equipmentByType', { type = '2' })
testIterator('equipmentByType', { type = '1', sort = '_icon' })
testIterator('equipmentByTypeAndIcon', { type = '1', icon = '16' })
testIterator('equipmentBy', { pred = 'is_large_caliber_main_gun', sort = '_type' })
testIterator('enemiesByType', { type = '2' })
end
-- p.test()
return Iterator