Exercise 9 Tests

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Plato.Core;
using Plato.Core.Search;
using Plato.Language;
using Plato.Language.Parser;
using Plato.Core.Parser;

namespace Tests
{
    [TestFixture]
    public class Exercise9
    {
        Brain brain;
        Parser parser;
        TransformationParser transParser;
        WordMappingParser wordMappingParser;

        [SetUp]
        public void SetUp()
        {
            brain = new Brain();
            parser = new Parser(brain);
            transParser = new TransformationParser(brain);
            wordMappingParser = new WordMappingParser(brain);

            brain.CreateEntity("noun");

            parser.Parse(
@"speaker is_a person
self is_a person
person has_a first_name
person has_a age
'Daniel' is_a first_name
27 is_a number
number is_a age
'Plato'
self.first_name = 'Plato'
self.age = 51
'first'
person has_a eye
eye has_a color
blue is_a color
DanielBigham is_a person
DanielBigham is_a man
man has_a wife
wife is_a person
'Meredith' is_a first_name
person has_a last_name
'Bigham' is_a last_name
last_name is_a noun
sister is_a person
person has(count:0+) sister
plural_noun is_a noun");

            wordMappingParser.Parse(
@"'name' -> first_name: noun
'nom' -> first_name: noun
'age' -> age: noun
'27' -> 27: noun
'I' -> speaker: noun
'you' -> self: noun
'is' -> is_am_are: verb
'am' -> is_am_are: verb
'are' -> is_am_are: verb
'eye' -> eye: noun
'color' -> color: noun
'colour' -> color: noun
'blue' -> blue: noun
'Daniel' -> DanielBigham: noun
'person' -> person: noun
'wife' -> wife: noun
'has' -> has_have: verb
'have' -> has_have: verb
'sisters' -> sister: plural_noun
'two' -> 2: noun");

            transParser.Parse(
@"my {noun} -> speaker.$1
mon {noun} -> speaker.$1
{noun} is {noun} -> $1 = $2
{noun} est {noun} -> $1 = $2
what is {noun} ? -> $1
{person} {is_am_are} {number} -> $1.age = $3
your {noun} -> self.$1
how old {is_am_are} {noun} ? -> $2.age
first name -> first_name
{noun} {noun} -> $1.$2
{noun} 's {noun} -> $1.$2
last name -> last_name
{noun} {has_have} {number} {noun} -> $1 has(count:$3) $4");
        }

        /// <summary>
        /// Test the TransformationSearch.ApplyTransformation method.
        /// </summary>
        [Test]
        public void TransformationSearch_ApplyTransformation_Test1()
        {
            TransformationSearch search =
                new TransformationSearch(brain, "My name is Daniel");
            search.Init();

            Fragment f = HelperFunctions.GetFragment(
                search.Fragments, "{'my'} {noun} {'is'} {noun}");

            Transformation t = brain.FindTransformations("'my'", "noun")[0];
            IList<IToken> variables;
            t.Matches(f, 0, out variables);

            IList<ITransOutput> outputs =
                TransformationSearch.ApplyTransformation(brain, t, f, 0, variables);

            Assert.AreEqual("speaker.first_name", outputs[0].ToString());
        }

        /// <summary>
        /// Test the resolution of a variable entity given an IsATree and
        /// a parent relationship.
        /// </summary>
        [Test]
        public void Resolve_ParentRelationship()
        {
            EntityTree tree = brain.Get("'Daniel'").GetIsATree();

            EntityTreeNode node = tree.Root.Children[1].Children[2];
            Assert.AreEqual("noun", node.Entity.Id);
            Assert.AreEqual("DanielBigham", node.Parents[2].Entity.Id);

            IToken parent = new EntityTypeToken(brain.Get("person"));

            IList<IEntity> resolvedEntities =
                TransformationSearch.Resolve(brain, node, parent, null,
                                             RelationType.Child_IsA_Parent,
                                             RelationType.None);

            Assert.AreEqual(1, resolvedEntities.Count);
            Assert.AreEqual("DanielBigham", resolvedEntities[0].Id);
        }

        /// <summary>
        /// Test the resolution of a variable entity given an IsATree and
        /// a child relationship.
        /// </summary>
        [Test]
        public void Resolve_ChildRelationship()
        {
            EntityTree tree = brain.Get("speaker").GetIsATree();

            EntityTreeNode node = tree.Root.Children[0].Children[0];

            IToken child = new EntityTypeToken(brain.Get("age"));

            IList<IEntity> resolvedEntities =
                TransformationSearch.Resolve(brain, node, null, child,
                                             RelationType.None,
                                             RelationType.Parent_HasA_Child);

            Assert.AreEqual(1, resolvedEntities.Count);
            Assert.AreEqual("speaker", resolvedEntities[0].Id);
        }

        /// <summary>
        /// My last name is Bigham
        /// </summary>
        [Test]
        public void Story1()
        {
            new StoryTest(
                brain,
                "My last name is Bigham",
                "speaker.last_name = 'Bigham'",
                null).RunTest();
        }

        /// <summary>
        /// My eye color is blue, What is my eye color?
        /// </summary>
        [Test]
        public void Story2()
        {
            new StoryTest(
                brain,
                "My eye color is blue",
                "speaker.eye.color = blue",
                null).RunTest();

            new StoryTest(
                brain,
                "What is my eye color?",
                "speaker.eye.color",
                "blue").RunTest();
        }

        /// <summary>
        /// I have 2 sisters
        /// </summary>
        [Test]
        public void Story3()
        {
            new StoryTest(
                brain,
                "I have 2 sisters",
                "speaker has(count:2) sister",
                null).RunTest();
        }

        /// <summary>
        /// I have two sisters
        /// </summary>
        [Test]
        public void Story4()
        {
            new StoryTest(
                brain,
                "I have two sisters",
                "speaker has(count:2) sister",
                null).RunTest();
        }

        /// <summary>
        /// Implicitly create entities for n+ (greater than or equal to)
        /// </summary>
        [Test]
        public void GreaterThanOrEqualTo()
        {
            IEntity entity = brain.Get("0+");

            Assert.AreEqual("0+", entity.Id);
        }

        /// <summary>
        /// Ability to create relationships that have key/value arguments.
        /// </summary>
        [Test]
        public void RelationshipArguments()
        {
            // person has(0+) sister
            IEntity person = brain.Get("person");
            IEntity sister = brain.Get("sister");
            IEntity has = brain.Get("has");
            IDictionary<string,IEntity> args = new Dictionary<string,IEntity>();
            args.Add("count", brain.Get("0"));
            brain.CreateRelationship(person, has, sister, args, true);
        }
    }

    /// <summary>
    /// Evaluate a story and ensure its expected output is as expected.
    /// </summary>
    internal class StoryTest
    {
        Brain brain;
        private string input;
        private string expectedTransOutput;
        private string expectedValue;

        public StoryTest(Brain brain, string input, string expectedTransOutput,
                         string expectedValue)
        {
            this.brain = brain;
            this.input = input;
            this.expectedTransOutput = expectedTransOutput;
            this.expectedValue = expectedValue;
        }

        public void RunTest()
        {
            TransformationSearch search = new TransformationSearch(brain, input);
            search.Search();

            Assert.AreEqual(1, search.Output.Count);
            Assert.AreEqual(expectedTransOutput, search.Output[0].ToString());

            if (search.Output[0] is TransOutput_Assignment)
            {
                // Execute the assignment
                Parser parser = new Parser(brain);
                parser.Parse(search.Output[0].ToString());
            }

            if (expectedValue != null)
            {
                Assert.AreEqual(expectedValue,
                    brain.GetValue(
                        ((TransOutput_Value)search.Output[0]).Property.ToString()).Id);
            }
        }
    }
}