greeting evaluation
This commit is contained in:
parent
d6aa54dbe0
commit
117dd6a1af
@ -20,6 +20,18 @@
|
|||||||
"4" : {
|
"4" : {
|
||||||
"id" : 4,
|
"id" : 4,
|
||||||
"name" : "Other"
|
"name" : "Other"
|
||||||
|
},
|
||||||
|
"5" : {
|
||||||
|
"id" : 5,
|
||||||
|
"name" : "Quote"
|
||||||
|
},
|
||||||
|
"6" : {
|
||||||
|
"id" : 6,
|
||||||
|
"name" : "Conversation"
|
||||||
|
},
|
||||||
|
"7" : {
|
||||||
|
"id" : 7,
|
||||||
|
"name" : "CurrentConversation"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations" : {
|
"relations" : {
|
||||||
@ -46,6 +58,18 @@
|
|||||||
"name" : "InstanceOf",
|
"name" : "InstanceOf",
|
||||||
"parent" : 3,
|
"parent" : 3,
|
||||||
"child" : 4
|
"child" : 4
|
||||||
|
},
|
||||||
|
"4" : {
|
||||||
|
"id" : 4,
|
||||||
|
"name" : "ParticipantOf",
|
||||||
|
"parent" : 7,
|
||||||
|
"child" : 4
|
||||||
|
},
|
||||||
|
"5" : {
|
||||||
|
"id" : 5,
|
||||||
|
"name" : "ParticipantOf",
|
||||||
|
"parent" : 7,
|
||||||
|
"child" : 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
21
src/main/java/org/studiorailgun/AI.java
Normal file
21
src/main/java/org/studiorailgun/AI.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package org.studiorailgun;
|
||||||
|
|
||||||
|
import org.studiorailgun.conversation.Quote;
|
||||||
|
import org.studiorailgun.conversation.evaluators.EvaluationTree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The top level ai class
|
||||||
|
*/
|
||||||
|
public class AI {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simulates a frame of the ai
|
||||||
|
* @param input The raw input text
|
||||||
|
*/
|
||||||
|
public static void simFrame(String input){
|
||||||
|
Quote playerQuote = new Quote(input);
|
||||||
|
//handle ai statement
|
||||||
|
EvaluationTree.evaluate(Globals.conversation, playerQuote);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ package org.studiorailgun;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import org.studiorailgun.conversation.Conversation;
|
import org.studiorailgun.conversation.Conversation;
|
||||||
|
import org.studiorailgun.conversation.evaluators.GreetingEval;
|
||||||
import org.studiorailgun.knowledge.KnowledgeWeb;
|
import org.studiorailgun.knowledge.KnowledgeWeb;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,17 +24,15 @@ public class Globals {
|
|||||||
/**
|
/**
|
||||||
* Initializes the knowledge web
|
* Initializes the knowledge web
|
||||||
*/
|
*/
|
||||||
public static void init(){
|
public static void init(String webPath){
|
||||||
Globals.loadWeb("web.json");
|
//initialize evaluators
|
||||||
}
|
GreetingEval.init();
|
||||||
|
|
||||||
/**
|
//init web
|
||||||
* Loads a web
|
Globals.web = FileUtils.loadObjectFromFile(new File(webPath), KnowledgeWeb.class);
|
||||||
* @param webPath The web's path
|
|
||||||
*/
|
|
||||||
public static void loadWeb(String webPath){
|
|
||||||
Globals.web = FileUtils.loadObjectFromFile(new File("web.json"), KnowledgeWeb.class);
|
|
||||||
Globals.web.initLinks();
|
Globals.web.initLinks();
|
||||||
|
|
||||||
|
//init convo
|
||||||
Globals.conversation = Conversation.parse(Globals.web);
|
Globals.conversation = Conversation.parse(Globals.web);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,10 +2,9 @@ package org.studiorailgun.conversation;
|
|||||||
|
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
import org.studiorailgun.AI;
|
||||||
import org.studiorailgun.Globals;
|
import org.studiorailgun.Globals;
|
||||||
import org.studiorailgun.conversation.llm.Actor;
|
import org.studiorailgun.conversation.evaluators.EvaluationTree;
|
||||||
import org.studiorailgun.conversation.llm.LLMConversation;
|
|
||||||
import org.studiorailgun.conversation.llm.Statement;
|
|
||||||
import org.studiorailgun.conversation.parser.CommandParser;
|
import org.studiorailgun.conversation.parser.CommandParser;
|
||||||
|
|
||||||
public class AgentLoop {
|
public class AgentLoop {
|
||||||
@ -24,18 +23,11 @@ public class AgentLoop {
|
|||||||
* The main method
|
* The main method
|
||||||
*/
|
*/
|
||||||
public static void main(){
|
public static void main(){
|
||||||
Globals.init();
|
Globals.init("web.json");
|
||||||
|
|
||||||
try (Scanner scan = new Scanner(System.in)) {
|
try (Scanner scan = new Scanner(System.in)) {
|
||||||
String prompt = "";
|
String prompt = "";
|
||||||
|
|
||||||
//setup conversation tracking
|
|
||||||
LLMConversation convo = new LLMConversation();
|
|
||||||
Actor player = new Actor("John");
|
|
||||||
Actor ai = new Actor("Dave");
|
|
||||||
convo.addParticipant(player);
|
|
||||||
convo.addParticipant(ai);
|
|
||||||
|
|
||||||
//actual main loop
|
//actual main loop
|
||||||
while(running){
|
while(running){
|
||||||
|
|
||||||
@ -44,10 +36,7 @@ public class AgentLoop {
|
|||||||
if(CommandParser.parseCommands(prompt)){
|
if(CommandParser.parseCommands(prompt)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
convo.addStatement(new Statement(player, prompt));
|
AI.simFrame(prompt);
|
||||||
|
|
||||||
//handle ai statement
|
|
||||||
throw new UnsupportedOperationException("asdf");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
package org.studiorailgun.conversation;
|
package org.studiorailgun.conversation;
|
||||||
|
|
||||||
import org.studiorailgun.conversation.evaluators.GreetingData;
|
import org.studiorailgun.conversation.evaluators.GreetingData;
|
||||||
|
import org.studiorailgun.conversation.evaluators.goal.GoalData;
|
||||||
import org.studiorailgun.knowledge.KnowledgeWeb;
|
import org.studiorailgun.knowledge.KnowledgeWeb;
|
||||||
|
import org.studiorailgun.knowledge.Node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A conversation
|
* A conversation
|
||||||
@ -18,35 +20,51 @@ public class Conversation {
|
|||||||
*/
|
*/
|
||||||
ConvParticipant other;
|
ConvParticipant other;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The node in the knowledge web representing this conversation
|
||||||
|
*/
|
||||||
|
Node data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data on greetings
|
* Data on greetings
|
||||||
*/
|
*/
|
||||||
GreetingData greetingData;
|
GreetingData greetingData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The goal data
|
||||||
|
*/
|
||||||
|
GoalData goalData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the current conversation's data from the knowledge web
|
* Parses the current conversation's data from the knowledge web
|
||||||
* @param web The web
|
* @param web The web
|
||||||
* @return The conversation
|
* @return The conversation
|
||||||
*/
|
*/
|
||||||
public static Conversation parse(KnowledgeWeb web){
|
public static Conversation parse(KnowledgeWeb web){
|
||||||
|
Node node = web.getNode(7);
|
||||||
|
|
||||||
//find the self
|
//find the self
|
||||||
ConvParticipant self = new ConvParticipant(web.getSelf());
|
ConvParticipant self = new ConvParticipant(web.getSelf());
|
||||||
|
|
||||||
//find the other participant
|
//find the other participant
|
||||||
ConvParticipant other = new ConvParticipant(web.getNode(4));
|
ConvParticipant other = new ConvParticipant(web.getNode(4));
|
||||||
|
|
||||||
Conversation rVal = new Conversation(self, other);
|
Conversation rVal = new Conversation(node, self, other);
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
* @param node The node representing this conversation instance
|
||||||
* @param self The participant representing this bot instance
|
* @param self The participant representing this bot instance
|
||||||
* @param other The participant representing the other party in the conversation
|
* @param other The participant representing the other party in the conversation
|
||||||
*/
|
*/
|
||||||
public Conversation(ConvParticipant self, ConvParticipant other){
|
public Conversation(Node node, ConvParticipant self, ConvParticipant other){
|
||||||
|
this.data = node;
|
||||||
this.self = self;
|
this.self = self;
|
||||||
this.other = other;
|
this.other = other;
|
||||||
|
this.greetingData = new GreetingData();
|
||||||
|
this.goalData = new GoalData();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,4 +91,14 @@ public class Conversation {
|
|||||||
return other;
|
return other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GoalData getGoalData() {
|
||||||
|
return goalData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGoalData(GoalData goalData) {
|
||||||
|
this.goalData = goalData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
48
src/main/java/org/studiorailgun/conversation/Quote.java
Normal file
48
src/main/java/org/studiorailgun/conversation/Quote.java
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package org.studiorailgun.conversation;
|
||||||
|
|
||||||
|
import org.studiorailgun.conversation.categorization.SentenceFunctionCategorizor.SentenceFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A quote stated during the conversation
|
||||||
|
*/
|
||||||
|
public class Quote {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The raw text of the quote
|
||||||
|
*/
|
||||||
|
String raw;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function of the sentence
|
||||||
|
*/
|
||||||
|
SentenceFunction function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param input The raw text of the quote
|
||||||
|
*/
|
||||||
|
public Quote(String input){
|
||||||
|
this.raw = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the raw text of the quote
|
||||||
|
* @return The raw text of the quote
|
||||||
|
*/
|
||||||
|
public String getRaw(){
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the function of the quote
|
||||||
|
* @return The function
|
||||||
|
*/
|
||||||
|
public SentenceFunction getFunction(){
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFunction(SentenceFunction function){
|
||||||
|
this.function = function;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
package org.studiorailgun.conversation.categorization;
|
package org.studiorailgun.conversation.categorization;
|
||||||
|
|
||||||
|
import org.studiorailgun.conversation.Quote;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Categorizes sentences based on function
|
* Categorizes sentences based on function
|
||||||
*/
|
*/
|
||||||
@ -10,27 +12,35 @@ public class SentenceFunctionCategorizor {
|
|||||||
*/
|
*/
|
||||||
public static enum SentenceFunction {
|
public static enum SentenceFunction {
|
||||||
/**
|
/**
|
||||||
* Transfers information to the other party
|
* A sentence whose purpose is to perform some non-informational duty in a conversation.
|
||||||
* ie, declaring facts, declaring perspective of the world (how you feel), etc
|
* An example of this could be a greeting or farewell.
|
||||||
* "The ball is red". "I don't like that".
|
|
||||||
*/
|
*/
|
||||||
TRANSFER_INFORMATION,
|
UTILITY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query information from the other party
|
* Transfers a piece of information to another participant. For instance, describing
|
||||||
* ie, asking for a fact or perspective
|
* the details of an object.
|
||||||
* "Is that ball red?" "What color is your hat?" "How do you feel about that?"
|
|
||||||
*/
|
*/
|
||||||
QUERY_INFORMATION,
|
TRANSFER,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries a piece of information from another participant.
|
||||||
|
*/
|
||||||
|
QUERY,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commands a participant to do something.
|
||||||
|
*/
|
||||||
|
IMPERATIVE,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Categorizes the sentence by function
|
* Categorizes the sentence by function
|
||||||
* @param input The input sentence
|
* @param input The input quote
|
||||||
* @return The function of the sentence
|
* @return The function of the sentence
|
||||||
*/
|
*/
|
||||||
public static SentenceFunction categorize(String input){
|
public static void categorize(Quote input){
|
||||||
return SentenceFunction.QUERY_INFORMATION;
|
input.setFunction(SentenceFunction.UTILITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,38 @@
|
|||||||
|
package org.studiorailgun.conversation.evaluators;
|
||||||
|
|
||||||
|
import org.studiorailgun.conversation.Conversation;
|
||||||
|
import org.studiorailgun.conversation.Quote;
|
||||||
|
import org.studiorailgun.conversation.categorization.SentenceFunctionCategorizor;
|
||||||
|
import org.studiorailgun.conversation.evaluators.goal.GoalEval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates a sentence based on data about the sentence
|
||||||
|
*/
|
||||||
|
public class EvaluationTree {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates a quote
|
||||||
|
* @param quote The quote
|
||||||
|
*/
|
||||||
|
public static void evaluate(Conversation conversation, Quote quote){
|
||||||
|
//parse data about the quote
|
||||||
|
SentenceFunctionCategorizor.categorize(quote);
|
||||||
|
|
||||||
|
//perform actions based on the tree
|
||||||
|
switch(quote.getFunction()){
|
||||||
|
case UTILITY: {
|
||||||
|
GreetingEval.evaluate(conversation, quote);
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//evaluate the AI's current goal in the conversation
|
||||||
|
GoalEval.evaluate(conversation);
|
||||||
|
|
||||||
|
//synthesize language based on the results of the actions performed
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -5,7 +5,9 @@ import java.io.IOException;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.studiorailgun.conversation.ConvParticipant;
|
||||||
import org.studiorailgun.conversation.Conversation;
|
import org.studiorailgun.conversation.Conversation;
|
||||||
|
import org.studiorailgun.conversation.Quote;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates a greeting
|
* Evaluates a greeting
|
||||||
@ -32,9 +34,12 @@ public class GreetingEval {
|
|||||||
* Evaluates a greeting
|
* Evaluates a greeting
|
||||||
* @param input The sentence
|
* @param input The sentence
|
||||||
*/
|
*/
|
||||||
public static void evaluate(Conversation conversation, String input){
|
public static void evaluate(Conversation conversation, Quote input){
|
||||||
if(greetingStrings.contains(input)){
|
if(greetingStrings.contains(input.getRaw())){
|
||||||
System.out.println("Contained!");
|
ConvParticipant other = conversation.getOther();
|
||||||
|
if(!conversation.getGreetingData().getHaveGreeted().contains(other)){
|
||||||
|
conversation.getGreetingData().getHaveGreeted().add(other);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,34 @@
|
|||||||
|
package org.studiorailgun.conversation.evaluators.goal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data about the AI's goal in the conversation
|
||||||
|
*/
|
||||||
|
public class GoalData {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A goal the ai can have for the conversation
|
||||||
|
*/
|
||||||
|
public static enum ConversationGoal {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Say a greeting
|
||||||
|
*/
|
||||||
|
GREET,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The goal of the conversation
|
||||||
|
*/
|
||||||
|
ConversationGoal goal;
|
||||||
|
|
||||||
|
public ConversationGoal getGoal() {
|
||||||
|
return goal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGoal(ConversationGoal goal) {
|
||||||
|
this.goal = goal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package org.studiorailgun.conversation.evaluators.goal;
|
||||||
|
|
||||||
|
import org.studiorailgun.conversation.ConvParticipant;
|
||||||
|
import org.studiorailgun.conversation.Conversation;
|
||||||
|
import org.studiorailgun.conversation.evaluators.GreetingData;
|
||||||
|
import org.studiorailgun.conversation.evaluators.goal.GoalData.ConversationGoal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates the AI's goal in the conversation
|
||||||
|
*/
|
||||||
|
public class GoalEval {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates the goal of the ai in the given conversation
|
||||||
|
* @param conversation The conversation
|
||||||
|
*/
|
||||||
|
public static void evaluate(Conversation conversation){
|
||||||
|
GreetingData greetingData = conversation.getGreetingData();
|
||||||
|
ConvParticipant selfParticipant = conversation.getSelf();
|
||||||
|
if(!greetingData.getHaveGreeted().contains(selfParticipant)){
|
||||||
|
conversation.getGoalData().setGoal(ConversationGoal.GREET);
|
||||||
|
} else {
|
||||||
|
conversation.getGoalData().setGoal(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -2,11 +2,7 @@ package org.studiorailgun;
|
|||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.studiorailgun.conversation.Conversation;
|
|
||||||
import org.studiorailgun.knowledge.KnowledgeWeb;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests loading conversations
|
* Tests loading conversations
|
||||||
@ -15,12 +11,9 @@ public class ConvLoadingTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadConversation(){
|
public void testLoadConversation(){
|
||||||
KnowledgeWeb web = FileUtils.loadObjectFromFile(new File("./data/test/webs/web.json"), KnowledgeWeb.class);
|
Globals.init("./data/test/webs/web.json");
|
||||||
web.initLinks();
|
assertEquals(Globals.web.getSelf(), Globals.conversation.getSelf().getData());
|
||||||
Globals.web = web;
|
assertNotEquals(Globals.web.getSelf(), Globals.conversation.getOther().getData());
|
||||||
Conversation convo = Conversation.parse(web);
|
|
||||||
assertEquals(web.getSelf(), convo.getSelf().getData());
|
|
||||||
assertNotEquals(web.getSelf(), convo.getOther().getData());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
21
src/test/java/org/studiorailgun/GreetingTests.java
Normal file
21
src/test/java/org/studiorailgun/GreetingTests.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package org.studiorailgun;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests greeting
|
||||||
|
*/
|
||||||
|
public class GreetingTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOtherGreeting(){
|
||||||
|
Globals.init("./data/test/webs/web.json");
|
||||||
|
|
||||||
|
AI.simFrame("Hello");
|
||||||
|
|
||||||
|
assertEquals(Globals.conversation.getGreetingData().getHaveGreeted().size(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
33
web.json
33
web.json
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"selfId": 2,
|
||||||
"nodes" : {
|
"nodes" : {
|
||||||
"0" : {
|
"0" : {
|
||||||
"id" : 0,
|
"id" : 0,
|
||||||
@ -18,7 +19,19 @@
|
|||||||
},
|
},
|
||||||
"4" : {
|
"4" : {
|
||||||
"id" : 4,
|
"id" : 4,
|
||||||
"name" : "ConversationParticipant"
|
"name" : "Other"
|
||||||
|
},
|
||||||
|
"5" : {
|
||||||
|
"id" : 5,
|
||||||
|
"name" : "Quote"
|
||||||
|
},
|
||||||
|
"6" : {
|
||||||
|
"id" : 6,
|
||||||
|
"name" : "Conversation"
|
||||||
|
},
|
||||||
|
"7" : {
|
||||||
|
"id" : 7,
|
||||||
|
"name" : "CurrentConversation"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations" : {
|
"relations" : {
|
||||||
@ -39,6 +52,24 @@
|
|||||||
"name" : "InstanceOf",
|
"name" : "InstanceOf",
|
||||||
"parent" : 1,
|
"parent" : 1,
|
||||||
"child" : 0
|
"child" : 0
|
||||||
|
},
|
||||||
|
"3" : {
|
||||||
|
"id" : 3,
|
||||||
|
"name" : "InstanceOf",
|
||||||
|
"parent" : 3,
|
||||||
|
"child" : 4
|
||||||
|
},
|
||||||
|
"4" : {
|
||||||
|
"id" : 4,
|
||||||
|
"name" : "ParticipantOf",
|
||||||
|
"parent" : 7,
|
||||||
|
"child" : 4
|
||||||
|
},
|
||||||
|
"5" : {
|
||||||
|
"id" : 5,
|
||||||
|
"name" : "ParticipantOf",
|
||||||
|
"parent" : 7,
|
||||||
|
"child" : 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user