Civilization Wiki
(Functional again, refactoring still in progress)
Tag: sourceedit
(still a work in progress. I've determined that it would be best if I revised the structure of the data modules. Ideally merge all subtables back into the main one.)
Tag: sourceedit
Line 112: Line 112:
 
end
 
end
 
}
 
}
  +
   
 
local objectMeta = {
 
local objectMeta = {
 
__index = function(o,k)
 
__index = function(o,k)
 
local class = o._classDefinition;
 
local class = o._classDefinition;
  +
if k == "_objectManager" then
  +
o[k] = require(class.ObjectsPath );
 
return o[k];
 
end
 
for i = 1, #class.StringFields do
 
for i = 1, #class.StringFields do
 
if k == class.StringFields[i] then
 
if k == class.StringFields[i] then
Line 136: Line 141:
 
for fieldName,className in pairs(class.ObjectFields) do
 
for fieldName,className in pairs(class.ObjectFields) do
 
if k == fieldName then
 
if k == fieldName then
o[k] = nil;
+
local id = o._objectFields[k];
return o[k];
+
if id then
  +
o[k] = o._objectManager.CreateObject(id,className);
end
 
end
+
return o[k];
  +
else
for fieldName,className in pairs(class.ObjectListFields) do
 
if k == fieldName then
+
return nil;
o[k] = nil;
+
end
return o[k];
 
 
end
 
end
 
end
 
end
Line 155: Line 159:
 
local ObjectClassDefinition = {ClassName = "Object"};
 
local ObjectClassDefinition = {ClassName = "Object"};
   
function _createObjectList(classDefinition)
+
function CreateObjectList(classDefinition)
 
classDefinition = classDefinition or ObjectClassDefinition;
 
classDefinition = classDefinition or ObjectClassDefinition;
local t = setmetatable(
+
local ol = setmetatable(
{SortByField = SortByField,
+
{SortByField = SortByField,
 
Sort = SortByField,
 
Sort = SortByField,
 
SortById = SortById,
 
SortById = SortById,
 
SortByName = SortByName,
 
SortByName = SortByName,
GetByField =GetByField,
+
GetByField = GetByField,
 
GetById = GetById,
 
GetById = GetById,
 
GetByName = GetByName,
 
GetByName = GetByName,
Line 170: Line 174:
 
Select = SelectField,
 
Select = SelectField,
 
ToString = ToString},objectListMeta);
 
ToString = ToString},objectListMeta);
t._classDefinition = classDefinition;
+
ol._classDefinition = classDefinition;
return classDefinition.ObjectListConstructor and classDefinition.ObjectListConstructor(t) or t;
+
return classDefinition.ObjectListConstructor and classDefinition.ObjectListConstructor(ol) or ol;
 
end
 
end
   
  +
local function UnindexObjectFields(o)
function _createObject(id,value,classDefinition)
 
  +
o._objectFields = {};
  +
for key,value in pairs(o) do
 
for fieldName,_ in pairs(o._classDefinition.ObjectFields) do
  +
if key == fieldName then
  +
o._objectFields[key] = value;
  +
o[key] = nil;
  +
end
  +
end
 
end
  +
end
  +
 
function CreateObject(id,value,classDefinition)
 
classDefinition = classDefinition or ObjectClassDefinition;
 
classDefinition = classDefinition or ObjectClassDefinition;
local t = utils.RecreateTable(value);
+
local o = utils.RecreateTable(value);
t.Id = id;
+
o.Id = id;
t._classDefinition = classDefinition or ObjectClassDefinition;
+
o._classDefinition = classDefinition or ObjectClassDefinition;
  +
UnindexObjectFields(o)
t = setmetatable(t,objectMeta);
+
o = setmetatable(o,objectMeta);
return classDefinition.ObjectConstructor and classDefinition.ObjectConstructor(t) or t;
+
return classDefinition.ObjectConstructor and classDefinition.ObjectConstructor(o) or o;
 
end
 
end
   
local function _fillObjectList(ol,data,classDefinition)
+
function FillObjectList(ol,data,classDefinition)
 
for k,v in pairs(data) do
 
for k,v in pairs(data) do
local o = _createObject(k,v,classDefinition);
+
local o = CreateObject(k,v,classDefinition);
 
if classDefinition.ObjectListInitialFilter then
 
if classDefinition.ObjectListInitialFilter then
 
if classDefinition.ObjectListInitialFilter(o) then
 
if classDefinition.ObjectListInitialFilter(o) then
Line 197: Line 214:
 
end
 
end
   
  +
function DEBUG()
local ObjectsManager = {};
 
  +
local data = require("Module:Data/Civ6/Base")
 
  +
local cd = require("Module:Data/Civ6/Base/Objects/Buildings");
function ObjectsManager.CreateObject(id,value,classDefinition)
 
  +
local ol = CreateObjectList(cd);
return _createObject(id,value,classDefinition)
 
  +
FillObjectList(ol,data.Buildings,cd)
end
 
  +
return ol;
 
function ObjectsManager.CreateObjectList(data,classDefinition)
 
local ol = _createObjectList(classDefinition)
 
return _fillObjectList(ol,data,classDefinition);
 
 
end
 
end
   
  +
return {CreateObject = CreateObject,
return ObjectsManager;
 
  +
CreateObjectList = CreateObjectList,
  +
FillObjectList = FillObjectList,
  +
DEBUG = DEBUG};

Revision as of 23:06, 28 October 2016

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

local utils = require("Module:TemplateUtils");

local function GetByField(self,field,value)
    for i = 1, #self do
       if self[i][field] and self[i][field] == value then
           return self[i]
       end
    end
end

local function GetById(self, id)
    return GetByField(self,"Id",id)
end

local function GetByName(self, name)
    return GetByField(self,"Name",name)
end

local function SortByField(self,field,desc)
    if desc then
        table.sort(self,function(a,b)
            return ( a[field] > b[field] )
        end)
    else
        table.sort(self,function(a,b)
            return ( a[field] < b[field] )
        end)
    end
    return self
end

local function SortById(self,desc)
    return SortByField(self,"Id",desc)
end

local function SortByName(self,desc)
    return SortByField(self,"Name",desc)
end

local comparators = {
    eq = function(a,b) return a == b end,
    neq = function(a,b) return not (a == b) end,
    lt = function(a,b) return a < b end,
    gt = function(a,b) return a > b end,
    lteq = function(a,b) return a <= b end,
    gteq = function(a,b) return a >= b end}

local function _selectComparator(c)
    if c == "eq" or c == "Equal" then return comparators.eq end;
    if c == "neq" or c == "NotEqual" then return comparators.neq end;
    if c == "lt" or c == "LessThan" then return comparators.lt end;
    if c == "gt" or c == "GreaterThan" then return comparators.gt end;
    if c == "lteq" or c == "LessThanOrEqual" then return comparators.lteq end;
    if c == "gteq" or c == "GreaterThanOrEqual" then return comparators.gteq end;
    return comparators.eq; -- Default
end

local function FilterByField(self,field,value,comparator)
    comparator = _selectComparator(comparator) or comparators.eq
    local t = _createObjectList(self._classDefinition)
    for i = 1, #self do
        if comparator(self[i][field],value) then
            table.insert(t,self[i])
        end
    end

    return t;
end

local function SelectField(self,field)
    local t = _createObjectList(self._classDefinition)
    for i = 1, #self do
        if self[i][field] then
            table.insert(t,self[i][field])
        end
    end
    return t;
end

local function ToString(self,field,separator)
    separator = separator or ", "
    local strings = {}
    for i = 1, #self do
        if field then
            if self[i][field] then
                table.insert(strings,tostring(self[i][field]))
            end
        else
            table.insert(strings,tostring(self[i]))
        end
    end
    return table.concat(strings,separator)
end

--ObjectList metatable
local objectListMeta = {
    --Alternative accessor by Id or Name
    __index=function(o,k)
                for i = 1, #o do
                   if o[i].Id and o[i].Id == k then
                       return o[i]
                   end
                end
                for i = 1, #o do
                   if o[i].Name and o[i].Name == k then
                       return o[i]
                   end
                end
        end,
    __tostring = function(o)
        return "{"..o._classDefinition.ClassName.."List"..":Count="..#o.."}"
    end
}


local objectMeta = {
    __index = function(o,k)
        local class = o._classDefinition;
        if k == "_objectManager" then
            o[k] = require(class.ObjectsPath );
            return o[k];
        end
        for i = 1, #class.StringFields do
            if k == class.StringFields[i] then
                o[k] = "";
                return o[k];
            end
        end
        for i = 1, #class.BooleanFields do
            if k == class.BooleanFields[i] then
                o[k] = false;
                return o[k];
            end
        end
        for i = 1, #class.NumberFields do
            if k == class.NumberFields[i] then
                o[k] = 0;
                return o[k];
            end
        end
        for fieldName,className in pairs(class.ObjectFields) do
            if k == fieldName then
                local id = o._objectFields[k];
                if id then
                    o[k] = o._objectManager.CreateObject(id,className);
                    return o[k];
                else
                    return nil;
                end
            end
        end
    end,
    __tostring = function(o)
        return "{"..o._classDefinition.ClassName..":"..(o.Id).."}"
    end
}

--Generic class definition when no other is available
local ObjectClassDefinition = {ClassName = "Object"};

function CreateObjectList(classDefinition)
    classDefinition = classDefinition or ObjectClassDefinition;
    local ol = setmetatable(
       {SortByField = SortByField,
        Sort = SortByField,
        SortById = SortById,
        SortByName = SortByName,
        GetByField = GetByField,
        GetById = GetById,
        GetByName = GetByName,
        FilterByField = FilterByField,
        Filter = FilterByField,
        SelectField = SelectField,
        Select = SelectField,
        ToString = ToString},objectListMeta);
    ol._classDefinition = classDefinition;
    return classDefinition.ObjectListConstructor and classDefinition.ObjectListConstructor(ol) or ol;
end

local function UnindexObjectFields(o)
    o._objectFields = {};
    for key,value in pairs(o) do
        for fieldName,_ in pairs(o._classDefinition.ObjectFields) do
            if key == fieldName then
               o._objectFields[key] = value;
               o[key] = nil;
            end
        end
    end
end

function CreateObject(id,value,classDefinition)
    classDefinition = classDefinition or ObjectClassDefinition;
    local o = utils.RecreateTable(value);
    o.Id = id;
    o._classDefinition = classDefinition or ObjectClassDefinition;
    UnindexObjectFields(o)
    o = setmetatable(o,objectMeta);
    return classDefinition.ObjectConstructor and classDefinition.ObjectConstructor(o) or o;
end

function FillObjectList(ol,data,classDefinition)
    for k,v in pairs(data) do
        local o = CreateObject(k,v,classDefinition);
        if classDefinition.ObjectListInitialFilter then
            if classDefinition.ObjectListInitialFilter(o)  then
                table.insert(ol,o);
            end
        else
            table.insert(ol,o);
        end
    end
    return ol;
end

function DEBUG()
    local data = require("Module:Data/Civ6/Base")
    local cd = require("Module:Data/Civ6/Base/Objects/Buildings");
    local ol = CreateObjectList(cd);
    FillObjectList(ol,data.Buildings,cd)
    return ol;
end

return {CreateObject = CreateObject,
        CreateObjectList = CreateObjectList,
        FillObjectList = FillObjectList,
        DEBUG = DEBUG};