Modelo de Metadados Extensível¶
O modelo de metadados fornece facilidades que normalmente não estão disponíveis em linguagens como C++. No C++, uma vez que uma classe foi definida, não é possível adicionar atributos; os atributos devem ser conhecidos em tempo de compilação e não é possível descobrir atributos em tempo de execução. Algumas linguagens fornecem tal funcionalidade, e muito mais, por exemplo, Java através de sua interface de Reflexão.
Dentro do Aimsun Next, scripting; o modelo meta extensível permite que atributos sejam adicionados a um objeto e que eles sejam descobertos dinamicamente à medida que os scripts são executados. O modelo de dados fornece:
- Extensibilidade: adicionando novos atributos a qualquer classe, para permitir a adição de novas informações a qualquer instância de objeto.
- Descoberta: detectando a existência de novos atributos em tempo de execução.
Tipos e Colunas¶
O modelo de Metadados é baseado em Tipos e Colunas. Tipo é sinônimo de classe, enquanto Coluna é sinônimo de atributo.
Criar um Tipo pode ser pensado como definir uma tabela, cujas colunas representam Colunas de Tipo e cujas linhas representam instâncias de Tipo (objetos).
TypeA:
ID Column1 Column2 Column3 Column4
1465 #### #### #### ####
3566 #### #### #### ####
Acessar o Tipo de um objeto informa se o objeto é uma seção, um centróide, um veículo, etc.
Exemplo de Código¶
Para obter o tipo de um objeto, chame o método getType()
t = myObject.getType()
print t.getName()
Onde t é uma instância da classe GKType. Se myObject é uma seção de via, chamar getName() em t retornará a string "GKSection".
Para obter a lista de colunas em um tipo:
cols = t.getColumns( GKType.eSearchOnlyThisType )
e para obter todos os nomes e valores dos atributos para o objeto:
for col in cols:
if col.getColumnType() != GKColumn._GKTimeSerie and myObject.getDataValue(col)[0] != None:
print col.getName()+": "+myObject.getDataValue(col)[0].toString()
Se um método de obtenção específico estiver disponível para acessar o atributo de um objeto, é mais conveniente chamá-lo
speed = section.getSpeed()
do que usar o modelo de metadados:
attr = section.getType().getColumn( "GKSection::speedAtt", GKType.eSearchThisAndParentTypes )
speed = section.getDataValueDouble( attr )
Para resumir, o modelo meta deve ser acessado quando:
- um método específico para recuperar os dados não existe, ou
- os dados foram adicionados em tempo de execução, portanto nenhum método de obtenção existe.
Deve-se observar que nem todos os atributos de um objeto são acessíveis através dos metadados.
Edição Meta por Script¶
Para ver quais colunas estão disponíveis em um Tipo, um método seria usar um script da seguinte forma:
sectionType = model.getType( "GKSection" )
attributes = sectionType.getColumns( GKType.eSearchOnlyThisType )
for x in attributes:
print "Nome :" + str(x.getName())
print "Nome Externo: " + str(x.getExternalName())
print "Tipo de Coluna: " + str(x.getColumnType())
print "Descrição: " +str(x.getDescription())
Para adicionar uma coluna:
sectionType.addExternalColumn( "GKSection::RoadNoiseFactor", "Fator de Ruído na Estrada", GKColumn.Double )
Edição Meta no Aimsun Next¶
Um método alternativo é usar a janela de Tipos do Aimsun Next e o Editor de Tipo. Selecione a opção de menu Janela/Janelas/Tipo. A janela de Tipos mostrará então todos os tipos no sistema.
Dê um duplo clique em um tipo para acessar seu editor.
Para adicionar um novo atributo ao tipo, selecione o botão Adicionar no editor.
Ao definir um novo nome único, use a convenção TypeName::Attribute. Isso garantirá que seja único em todo o modelo e não pode ser duplicado inadvertidamente em diferentes tipos.
O armazenamento para atributos pode ser definido pelo usuário como:
- Externo: Aimsun Next fornecerá armazenamento em memória e no arquivo ANG.
- Temporal: Aimsun Next fornecerá armazenamento em memória.
- Função: uma função Python.
Enquanto o tipo de dado pode ser Inteiro, Inteiro Sem Sinal, Booleano, Double, String, Objeto, ou Série Temporal. Note, no entanto, que o tipo Série Temporal não será salvo, mesmo que o armazenamento seja configurado como externo, portanto, quando o arquivo ANG for fechado e reaberto, o atributo ainda estará presente, mas estará vazio.
Para acessar o valor de dados acima, o código seria o seguinte:
attr = model.getColumn( "GKSection::RoadNoiseFactor" )
roadNoiseFactor = section.getDataValue( attr )
Todos os atributos definidos nativamente nas classes Aimsun Next têm um tipo de armazenamento Interno e, como tal, não são editáveis. Note também que atributos Externos não podem ser deletados ou editados, então quando tal atributo é criado, não é possível fazer alterações usando a janela do Editor de Tipo, no entanto, ele pode ser editado usando scripting.
O tipo de armazenamento Função permite que um atributo seja definido cujo conteúdo é calculado dinamicamente cada vez que é acessado (lido via GUI ou script Python). O cálculo é definido pela função Python fornecida na caixa de texto do diálogo código.
A função deve ser definida como:
def eval_attr( object ):
# computar o valor
return res
Onde object é uma referência ao objeto para o qual o atributo está sendo avaliado; res é o valor retornado pela função, que será o valor do atributo para o objeto. O tipo deve ser coerente com aquele selecionado como Tipo de Dado; a implementação atual suporta apenas Inteiro, Inteiro Sem Sinal, Booleano, Double e String.
Por exemplo, para comparar os fluxos de dois cenários de microsimulação, cujas médias de IDs são 2880 e 2890, defina um novo atributo conforme mostrado abaixo.
Note que séries temporais não podem ser armazenadas em um atributo definido como função, o valor agregado da série temporal de fluxo das médias deve ser calculado.
A opção Por Área atualmente não é utilizada. A opção Dinâmica é usada para especificar que o valor do atributo pode mudar mesmo que não seja modificado manualmente pelo usuário; apenas atributos dinâmicos podem ser usados para definir um acionador.