Star Trek Wrath of Gems Wikia
Advertisement

Documentation for this module may be created at Module:CommonCodes/doc

-- commoncodes module
-- inside: [[Category:Modules]] using this line once...
-- has common functions that will operate on/about starships/characters

-- BEWARE: these functions do not work well with testcases because
--          they do not take frame's for arguments usually...
-- HOWEVER: they need to copy-out their passed-in-args anyways because
--          otherwise nothing works as it should...  sigh...

-- <pre>

local p = {}
local getargs = getargs or require('Dev:Arguments').getArgs
local utils = utils or require('Module:Utilities')
local glbls = glbls or require('Module:Globals')
local blnks = blnks or require('Module:BlankCommons')

glbls.sorc = 'x'
glbls.typenameS = 'Module:Starshipcodes/'
glbls.typenameC = 'Module:Charactercodes/'
glbls.filename = 'data'
glbls.keysLoaded = false
glbls.keys = {}
glbls.data = {}
glbls.holdtbl = {}
glbls.frame0 = nil
glbls.args = {'junk',}
glbls.character = 'crewch'
glbls.starship = 'starsh'
glbls.dumpGLBL = 'TEST-dumpGLBL'
glbls.useMixedCaseKeys = false

function p.hello()
    return 'Hello, world!'
end

local function table_slice(tbl, first, last, step)
  local sliced = {}

  for i = first or 1, last or #tbl, step or 1 do
    sliced[#sliced+1] = tbl[i]
  end

  return sliced
end

function p.passGLBLsorc(frame)
    local fakeframe = {}
    local a,retval,retstr,teststr,teston
    fakeframe[1] = 'sorc'
    a = utils.tableShallowCopy(getargs(frame))
    -- extra args just ignored !!!
    fakeframe[2] = a[1]
    -- forward-call works because p. is already-declared...
    -- change/restore REAL frame ASAP
    glbls.frame0 = utils.tableShallowCopy(frame)
    retstr = p.passGLBL(fakeframe)
    frame = utils.tableShallowCopy(glbls.frame0)
    -- incongruous, but glbls.args get reset inside _main()
    glbls.args = utils.tableShallowCopy(a)
    -- error-checking for valid 's'-or-'c' argument...
    retval = false
    -- so many ways to do this test...
    -- v.4 length check !!!!!
    if string.len(glbls.sorc) > 2 then return false end
    if string.len(glbls.sorc) == 1 then
        -- v.1
        if utils.stringEnds(retstr,'s') then return true end
        if utils.stringEnds(retstr,'c') then return true end
    	-- v.2 (upper/lowercase ending-only)  -- retstr[#retstr]
        teststr = string.lower(string.sub(retstr,-1))
        if teststr=='s' or teststr=='c' then
    		glbls.sorc = teststr
    		return true
    	end
    end
	-- v.3 (filename-expansion allows SO,SN,CO,CN values)
    teststr = string.lower(string.sub(retstr,-2))
    teston = string.lower(string.sub(teststr,-1))
    if teston=='o' or teston=='n' then
        local finalsorc = string.sub(teststr,1,1)
        if finalsorc=='s' or finalsorc=='c' then
	    	glbls.sorc = finalsorc
		    return true
	    end
	end
    return retval
end

function p.passGLBL(frame)
    local what,whatval,a
    local retval = false
    if not p._main(frame) then return retval end
    a = glbls.args
    if #a ~= 2 then return retval end
-- no other error checks here...
    what = a[1]
    whatval = a[2]
    glbls[what] = whatval
    retval = 'glbls.'..what..'='..whatval
--    retval = true
    return retval
end

local function isGoodKey(k)
    local allKeys,found
    if k==nil then return false end
    if not glbls.keysLoaded then return false end
        found = false
    if glbls.data[k] then
		if glbls.useMixedCaseKeys then
			found = true
		elseif string.upper(k)==k then
			found = true
		else
			found = false
		end
    end
--    found = #glbls.keys
    return found
end
local function isGoodSkill(k,sknum)
    local retval = false
    if not isGoodKey(k) then return retval end
    if (sknum == nil) or (sknum < 1) then return retval end
    if sknum > 3 then return retval end
    local chose = 'desc'..sknum
    local chkTbl = glbls.data[k]['skills']
    if not chkTbl then return retval end
    -- at this point, lets save some effort later...
    glbls.holdtbl = utils.tableShallowCopy(chkTbl)
    -- this assumes the input-data has a 't1' beginning...
    local chkTV = chkTbl[chose]
    if not chkTV['t1'] then return retval end
    -- at this point, it should be good...
    retval = true
    return retval
end

function mkOKitems(sorc)
    local items = {},chkr
    if not sorc then sorc = glbls.sorc end
    if sorc == 's' then
        chkr = blnks.ship()
    elseif sorc == 'c' then
        chkr = blnks.crew()
    else -- only assumption...
        chkr = { name='', ignore={}, }
    end
    for k,v in pairs(chkr) do
        if utils.isSimple(v) then
            --items[#items+1]=k
            items[k]=k
        end
    end
    return items
end
function getFullKey(key)
    if isGoodKey(key) then
        return glbls.data[key]
    else
        -- never hits here ...
        return 'really nothing found'
    end
end
local function getTablefromKey(key,item)
    -- assumes prechecks already done...
    local retval
    if isGoodKey(key) then
        if not item then
            retval = 'NO-ITEM?...'
            retval = glbls.data[key].name
        else
            local tempval = glbls.data[key][item]
            if type(tempval) == 'table' then
                local enc = utils.JSONencodeTable2String(tempval)
--                retval = 'YEAH!'
--                retval = tempval
                retval = enc
            else
                retval = 'not-a-sub-table...'
            end
        end
--    else
--        retval = 'BAD-KEY?...'
    end
    return retval
end
local function getItemfromKey(key,item)
    -- assumes prechecks already done...
    local retval
    if isGoodKey(key) then
        if not item then
            retval = glbls.data[key].name
--            return glbls.data[key].name
        else
            retval = glbls.data[key][item]
--            return glbls.data[key][item]
        end
    end
    if not retval then retval = 'tbd...' end
    return retval
end
function getNamefromKey(key)
    return getItemfromKey(key)
end
function makeIGPTfromKey(key)
    local igp,tier,igpt
    igp = getItemfromKey(key,'igp')
    tier = getItemfromKey(key,'tier')
    igpt = ''..tostring(igp)..'-'..tostring(tier)
    return igpt
end

-- these are both skills (crew) and features (ship) defaults...
-- and since the assumptions are the same for each, there is no
-- reason to bring this code up-a-level to the crew/ship levels...
-- however, there needs to be a way to bring-the-data-down to
-- get the CORRECT selections for the table (esp the merges), so...
-- TVarr is specifically: #S is skill-#, #L is level-number
-- crew: key-CK, tbl-skills, subtbl-desc#S with merges due to
--               tbl-skillsUpgrades, subtbl-supgr#L and subsubtbl-desc#S
-- ship: exact same tbl-names and uses, just different keys...
local function reduceTV(tbl)
        local descStr = ''
        -- literally assume that t- and v- items alternate and never go above t6...
        local chk = { 't1','v1','t2','v2','t3','v3','t4','v4','t5','v5','t6', }
        for i = 1,#chk do
            local subk, subv = chk[i], tbl[chk[i]]
            if subv ~= nil then descStr = descStr .. subv end
        end
        return descStr
end
local function isGoodSKitem(itm)
    local retval = false
    local poss = { 'skill', 'color', 'cost', 'desc' }
    -- special-case, let 'name' be synonym for 'skill'...
    poss[#poss+1] = 'name'
    if not itm then return retval end
    -- note: skill1 or color3 are NOT valid calls for itm
    -- because we have sknum as separate variable in chooseSK...
    for _,i in ipairs(poss) do
        if itm == i then retval = true end
    end
    return retval
end
local function chooseSKcost(k,sn,sup)
    -- similar to SK2reduceTV, have to reach-down to be sure that costs
    -- havent changed at sub-supgr#L and subsubitem-cost#S
    local retval = 999
    return retval
end
local function chooseSK2reduceTV(k,sn,sup)
    -- just return a table that can be passed into reduceTV...
    local sktbl,skuptbl
    local rettbl = {}
    -- should do checks here to be sure table is kosher before passing...
    rettbl[t1]='t1 is '
    rettbl[v1]=2
    return rettbl
end
local function chooseSK(key,sknum,item,skupg)
    -- basic SKcolor and SKname stay consistent by skill-number only...
    -- complex SKcost and SKdesc need further work on sk-upgrade to return...
    local retstr = ''
    -- should do checks here to be sure selections are ok...
    if isGoodKey(key) then
        -- tables get passed JSON-encoded, which is a bit silly...
        -- so skip/ignore or do-another-way...
        --local sktbl = getTablefromKey(key,'skills')
        local sktbl = glbls.data[key]['skills']
        local subitem = {}
        if isGoodSkill(key,sknum) then
            -- use the passed-global skills-table...
            local curTBL = glbls.holdtbl
            local act
            if isGoodSKitem(item) then
                -- fix special-case...
                if item == 'name' then item = 'skill' end
                -- act has correct-named skill1, cost3, ...
                act = item..sknum
                subitem = curTBL[act]
            else
                retstr = 'nogood skill-item... ['..tostring(item)..']'
            end
            -- at this point subitem holds upgrade-0/1 value/s
            if (not skupg) or (skupg == 0) then skupg = 1 end
            -- assuming integers here...  sigh...
            if skupg ~= math.floor(skupg) then
                retstr = 'skill-upgrade not an integer...'
            end
            if (skupg > 5) or (skupg < 1) then
                retstr = 'skill-upgrade-failed... ['..tostring(skupg)..']'
            else
                -- we will need the upgrade-table now...
                local sups = 'supgr'..skupg
                if skupg > 1 then
                    curTBL = glbls.data[key]['skillsUpgrades'][sups][act]
                end
            end
            -- actually return result if level-1 else fixup upgrades
            if item == 'skill' then
                retstr = subitem
            end
            if item == 'color' then
                retstr = subitem
            end
            if item == 'cost' then
                retstr = subitem
--[[
                retstr = retstr..'cost upg-'..skupg..'\n'
                retstr = retstr..'curtbl='..utils.dumpTable(curTBL)..'\n'
                retstr = retstr..'sbitem='..utils.dumpTable(subitem)
--]]
                if skupg > 1 then
                    -- rather than do merge, just check directly...
                    if curTBL then
                        retstr = curTBL
                    end
                end
            end
            if item == 'desc' then
                retstr = reduceTV(subitem)
--[[
                retstr = retstr..'desc upg-'..skupg..'\n'
                retstr = retstr..'curtbl='..utils.dumpTable(curTBL)..'\n'
                retstr = retstr..'sbitem='..utils.dumpTable(subitem)
--]]
                if skupg > 1 then
                    if curTBL then
                        local mrg = utils.mergeTable(subitem,curTBL)
                        retstr = reduceTV(mrg)
                    end
                end
            end
            if retstr == '' then
                retstr = 'we fell thru without selecting anything...'
            end
        else
            retstr = 'skill number ['..tostring(sknum)..'] wasnt good...'
        end
    else
        retstr = 'need to loadup glbl.data with '..key..' data...'
    end
    return retstr
end

local function createSkillsValues(tbl)
    -- this function returns the skill1 thru desc3 section of Infoboxes...
    local retStr = ''
    for k,v in pairs(tbl) do
        if utils.isSimple(k) then
            if utils.isSimple(v) then
                retStr = retStr .. '| '..tostring(k)..' = ' ..v.. '\n'
            elseif type(v) == 'table' then
                retStr = retStr .. '| '..tostring(k)..' = '
                retStr = retStr .. reduceTVarrays(v) .. '\n'
            else
                retStr = retStr .. '| badValueForKey = ' ..tostring(k).. '\n'
            end
        else
            retStr = retStr .. '| badTypeForKey = "' ..type(k).. '"\n'
        end
    end
    return retStr
end




function isGoodList(args)
    local a={}
    local chk,ok
    ok = false
    chk = #args
    -- assumes args come in item,qty pairs
    -- first item ignored 'sorc' or 'list'
    if (chk > 1) and (chk % 2 == 1) then
        ok = true
        for i=2,chk do a[i-1]=args[i] end
    end
    return ok,a
end
function oneCharorShip(args)
    local key = args[1]
    local num = args[2]
    return num..' '..getNamefromKey(key)..' '
end
function listofCharsorShips(args)
    --return 'args are :' .. utils.dumpTable(args)
    local ok,reargs = isGoodList(args)
    if not ok then return 'Lists must be in name,number pairs' end
    local numLoops = #reargs/2  -- known integral from caller...
    local subargs = {}
    local tempstr, retval
    local substrs = {}
        for i = 1,numLoops do
            subargs[1] = reargs[2*(i-1)+1]
            subargs[2] = reargs[2*(i-1)+2]

            tempstr = oneCharorShip(subargs)
                substrs[#substrs+1] = tempstr
        end
    if #substrs == 1 then
        retval = substrs[1]
    elseif #substrs == 2 then
        retval = substrs[1]..' and '..substrs[2]
    else
        retval = substrs[1]
        for i = 2,#substrs-1 do
            retval = retval..', '..substrs[i]
        end
        retval = retval..', and '..substrs[#substrs]
    end
    return retval
end




local function dumpArgs()
    local retstr='glbls.args='
    retstr = retstr..utils.dumpTable(glbls.args)
    return retstr
end
local function loadDataNow()
    local sorc = glbls.sorc
    local fn,alldata,allkeys,k
    -- needed to pass in sorc
    if sorc == 's' then
        fn = glbls.typenameS..glbls.filename
    elseif sorc == 'c' then
        fn = glbls.typenameC..glbls.filename
    else
        fn = nil
    end
    if fn then
        alldata = mw.loadData(fn)
    else
        alldata = {}
    end
	-- allkeys = glbls.keys  -- empty, supposedly...
	allkeys = {}
    for _,k in ipairs(alldata) do
        allkeys[#allkeys+1] = k
    end
    glbls.data = utils.tableShallowCopy(alldata)
    glbls.keys = utils.tableShallowCopy(allkeys)
    glbls.keysLoaded = true
    return true
end

local function listDBstring(argsel)
	local tempstr='CommonCodes bad-listDBstring :'
	local fullsel,keyitem,dummy,alldata,allkeys
	local selitem,selvalue
	fullsel = argsel[1]
	keyitem = argsel[2]
	-- we are done with these items???
	if #argsel > 2 then
		--table.remove(argsel,1)
		--table.remove(argsel,1)
		--selitem = argsel[1]
		--selvalue = argsel[2]
		selitem = argsel[3]
		selvalue = argsel[4]
	end
	-- for now only allow simple tier=2 type of qualifiers...
	if #argsel > 4 then
		tempstr = tempstr..'too-many-qualifiers ???'
		-- force-dump-early...
		keyitem = 'XXXXXXXXX'
	end
	if not string.find(keyitem,'key') then
		tempstr = tempstr..dumpArgs()
	else
	-- currently we ONLY know how to deal with keylist,keycount,keyTbl...
		-- first, we preload the database...
			if glbls.sorc=='s' then
				dummy = getNamefromKey('EN')
			elseif glbls.sorc=='c' then
				dummy = getNamefromKey('CK')
			else
				dummy = getNamefromKey('XXX')
			end
		-- next we make a current sorted-GOOD-key-index...
			alldata = utils.tableShallowCopy(glbls.data)
			allkeys = {}
			for k,_ in utils.tableSort(alldata) do
				if isGoodKey(k) then
					-- drops mixedCaseKeys...
					allkeys[#allkeys+1] = k
				end
			end
			dummy = utils.tableShallowCopy(allkeys)
		-- next we deal with valid 'full' keywords
			if fullsel == 'full' then
				if keyitem == 'keylist' then
					tempstr = utils.dumpTableSorted(dummy)
				elseif keyitem == 'keycount' then
					tempstr = utils.tblFullSize(dummy)
				else -- keyTbl
					local fakeFrame = {}
					glbls.keys = dummy
						tempstr = utils.dumpTableSorted(dummy)
						fakeFrame[1] = 'keys'
						fakeFrame[2] = utils.JSONencodeTable2String(dummy)
						tempstr = p.passGLBL(fakeFrame)
				end
		-- finally we deal with 'selects'
			else
				--tempstr = 'select-item='..selitem..'  selval='..selvalue
				-- create idx_by_subitem...
				local keys_bysub_match
				local SL = string.lower
				--local SFD = string.find
				keys_bysub_match = {}
				for _,k in ipairs(allkeys) do
					for sk,sv in pairs(alldata[k]) do
						if string.find(SL(sk),SL(selitem)) then
							if string.find(SL(sv),SL(selvalue)) then
								keys_bysub_match[#keys_bysub_match + 1] = k
							end
						end
					end
				end
				-- BEWARE this is a greedy-match so:
				-- selitem= tier, selvalue= 3 WILL match...
				--   BackTieRodeo , 123.45
				if keyitem == 'keylist' then
					tempstr = utils.dumpTableSorted(keys_bysub_match)
				elseif keyitem == 'keycount' then
					tempstr = utils.tblFullSize(keys_bysub_match)
				end

			end

	end

	return tempstr
end

function p.isGoodKey(frame)
    local sorc,k
    if not p._main(frame) then return false end
    -- catch these before fake-frame passing for GLBLsorc...
    sorc = glbls.args[1]
    k = glbls.args[2]
    if not p.passGLBLsorc(frame) then return false end
    if not loadDataNow() then return false end
    return isGoodKey(k)
end
function p.unwrapCaller(frame)
    -- these four items are all-returned-at-once !!!
    local sorc,key,nextArg,retval
    -- NIL is a valid return-value, so skipping...
--        sorc = ''
--        key = ''
--        nextArg = ''
    if not p.isGoodKey(frame) then
        retval = false
    else
        retval = true
        sorc = glbls.args[1]
        key = glbls.args[2]
        if #glbls.args > 2 then
            nextArg = glbls.args[3]
        end
    end
    return sorc,key,nextArg,retval
end
function p.getItemfromKey(frame)
    local dummy,key,item,ok
    local retval
    dummy,key,item,ok = p.unwrapCaller(frame)
    if not ok then return false end
    retval = getItemfromKey(key,item)
    return retval
--    if not utils.isSimple(retval) then return utils.dumpTable(retval) end
end
function p.getNamefromKey(frame)
    -- this has weird-issue due to extra-possible args...
    --   so we have to strip-ignore anything extra...
    local dummy,key,ignore,ok
    local retval
    dummy,key,ignore,ok = p.unwrapCaller(frame)
    if not ok then return false end
    retval = getNamefromKey(key)
    return retval
--    if not utils.isSimple(retval) then return utils.dumpTable(retval) end
end

function p.passTBL(frame)
    local dummy,key,item,ok
    local retval
    dummy,key,item,ok = p.unwrapCaller(frame)
    if not ok then return false end
    if not isGoodKey(key) then return false end
    retval = getTablefromKey(key,item)
    return retval
--    return 'tbd...'
end

function p.isGoodList(frame)
    -- weird overcall assuming item is a number...
    -- dropping reargs from return...
    local dummy,key,item,ok
    local retval
    dummy,key,item,ok = p.unwrapCaller(frame)
    if not ok then return false end
    if not tonumber(item) then return false end
    retval = isGoodList(glbls.args)
    return retval
--    if not utils.isSimple(retval) then return utils.dumpTable(retval) end
end
function p.getFullKey(frame)
    local dummy,key,dummy2,ok
    local retval
    dummy,key,dummy2,ok = p.unwrapCaller(frame)
    if not ok then return false end
    retval = getFullKey(key)
    return retval
--    if not utils.isSimple(retval) then return utils.dumpTable(retval) end
end
function p.mkOKitems(frame)
    local sorc,dummy,dummy2,ok
    local retval
    sorc,dummy,dummy2,ok = p.unwrapCaller(frame)
    if not ok then return false end
    retval = mkOKitems(sorc)
    return retval
--    if not utils.isSimple(retval) then return utils.dumpTable(retval) end
end
function p.makeIGPTfromKey(frame)
    local dummy,key,dummy2,ok
    local retval
    dummy,key,dummy2,ok = p.unwrapCaller(frame)
    if not ok then return false end
    retval = makeIGPTfromKey(key)
    return retval
--    if not utils.isSimple(retval) then return utils.dumpTable(retval) end
end
function p.SkFt(frame)
    local dummy,key,dummy2,ok
    local retval
    if not p._main(frame) then return false end
    -- catch these before fake-frame passing for GLBLsorc...
    sorc = glbls.args[1]
    k = glbls.args[2]
    skno = tonumber(glbls.args[3])
    skit = glbls.args[4]
    skup = tonumber(glbls.args[5])
    if not p.passGLBLsorc(frame) then return false end
    if not loadDataNow() then return false end
--    retval = 'gsk['..tostring(isGoodSkill(k,skno))..']'
--    retval = 'gskit['..tostring(isGoodSKitem(skit))..']'
--    return isGoodKey(k)
--local function chooseSK(key,sknum,item,skupg)
--    retval = 'k['..k..'],skno['..skno..'],skit['..skit..'],skup['..skup..']'
    retval = chooseSK(k,skno,skit,skup)
    return retval
end




function p._main(frame)
    -- this cleans up outside (or INside) calls for args
    local a
    local one,chkpairs
    a = utils.tableShallowCopy(getargs(frame))
    if #a == 0 then return false end
    glbls.args = a
    return true
end

function p.main(frame)
    local retval = 'invalid call to Commoncodes-main: '
    local a,sorc,mKey,mItem
    local tempStr
    if not p._main(frame) then
        retval = retval..'zero arguments passed'
        return retval
    end
    a = glbls.args
    sorc = a[1]
    mKey = a[2]
    mItem = a[3]
    if not p.passGLBLsorc(frame) then
		-- this is a complicated way to just check/set
		-- a single variable (glbls.sorc=frame.args[1]),
		-- but semi-necessary due to weird indirections
		-- that wikia-system forces onto frame-stuff...
        retval = retval..'invalid sorc-value >>'..sorc..'<<'
        return retval
    end
    if not loadDataNow() then
        retval = retval..'cannot loadData'
        return retval
    end
    --retval = utils.dumpTable(a)
    --retval = dumpArgs()
    if #a == 2 then
        retval = getItemfromKey(mKey)
    else
        local origokItems = { i='image', icon='image', image='image',
                    t='tier', tier='tier',
                    n='name', name='name',
                    g='govt', govt='govt',
                    s='series', series='series',  hp='hp',
                }
        local okItems1,okItems2,okItems
        -- we are DONE with sorc, so remove it... ???
        --table.remove(a,1)
        -- this returns a table with 'simple' item-values (non-subtables)
        okItems1 = mkOKitems(sorc)
        okItems = utils.mergeTable(okItems1,origokItems)
        retval = nil
        -- ORDER REVERSAL, the mKey is now the 'requested' item
        -- while the mItem is the 'key' character/ship...
        for k,v in pairs(okItems) do
            if mKey==k then
                retval = getItemfromKey(mItem,v)
            end
        end
        --retval = utils.dumpTableSorted(okItems1)
        if not retval then
				local b
				b = table_slice(a,2)
            if mKey == 'name' then
                -- allow reversal of arguments
                -- this should already be covered above...
                retval = getNamefromKey(mItem)
            elseif mKey == 'list' then
				-- this just makes the list pretty...
                retval = listofCharsorShips(b)
            elseif mKey == 'full' or
					mKey == 'select' then
				retval = listDBstring(b)
            elseif mKey == 'dumpGLBL' then
                local key,fk,urps
                key = mItem
                fk = getFullKey(key)
                urps = makeIGPTfromKey(key)
                glbls.dumpGLBL = 'sorc='..glbls.sorc
--                glbls.dumpGLBL = 'key='..key..' igpt='..urps
                --glbls.dumpGLBL = 'key='..key..' igpt='..urps..' fk='..utils.dumpTable(fk)
                retval = tostring(glbls.dumpGLBL)
            else
                retval = 'CommonCodes bad-which :'..dumpArgs()
            end
        end
    end
    return retval
end


return p
Advertisement