/// <summary>
        /// Creates a rank order from a list of categories with difficulty ratings.
        /// </summary>
        ///
        /// <param name="categories">List of categories.</param>
        ///
        /// <returns>RankOrder object</returns>
        public RankOrder createRankOrder(List <PCategory> categories)
        {
            if (categories.Find(category => !category.hasId()) != null)
            {
                Log(Severity.Error, "createRankOrder: Cannot create a rank order. Category ID  is missing. Returning null.");
                return(null);
            }

            // [SC] sorting by an ascending order of ID
            categories.Sort((catOne, catTwo) => catOne.Id.CompareTo(catTwo.Id));

            PCategory prevCat = null;

            foreach (PCategory category in categories)
            {
                if (!category.hasRating())
                {
                    Log(Severity.Error, String.Format("createRankOrder: Cannot create a rank order. Rating for category '{0}' is missing. Returning null.", category.Id));
                    return(null);
                }

                if (prevCat != null && prevCat.isSameId(category))
                {
                    Log(Severity.Error, String.Format("createRankOrder: Cannot create a rank order. Duplicate category ID is found: '{0}'. Returning null.", category.Id));
                    return(null);
                }

                prevCat = category;
            }

            // [SC] sorting by an ascending order of ratings
            categories.Sort((catOne, catTwo) => catOne.Rating.CompareTo(catTwo.Rating));

            // [SC] building ranks
            RankOrder rankOrder = new RankOrder(this.Threshold);
            int       rankIndex = 0;
            Rank      rank      = null;
            PCategory firstCat  = null;

            while (categories.Count > 0)
            {
                PCategory nextCat = categories[0];

                if (firstCat == null || this.isSignificantlyDifferent(firstCat.Rating, nextCat.Rating))
                {
                    rank = new Rank(++rankIndex);
                    rankOrder.addRank(rank);

                    firstCat = nextCat;
                }

                rank.addCategory(nextCat);
                categories.Remove(nextCat);
            }

            return(rankOrder);
        }
Exemple #2
0
        /// <summary>
        /// Remove category by its ID.
        /// </summary>
        ///
        /// <param name="id">category ID</param>
        ///
        /// <returns>true if a category was removed</returns>
        public bool removeCategory(String id)
        {
            PCategory remCat = categories.Find(category => category.isSameId(id));

            if (remCat != null)
            {
                categories.Remove(remCat);
                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemple #3
0
        /// <summary>
        /// Add a new category to the knowledge state.
        /// </summary>
        ///
        /// <param name="newCategory">PCategory objectt</param>
        ///
        /// <returns>true if category was added; false if a category with the same ID already exists in the list</returns>
        public bool addCategory(PCategory newCategory)
        {
            // [SC] a root state is always an empty state
            if (this.StateType.Equals(KSGenerator.ROOT_STATE))
            {
                return(false);
            }

            // [SC] verifying if a category with the same ID already exists
            if (this.categories.Find(category => category.isSameId(newCategory)) == null)
            {
                this.categories.Add(newCategory);
                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemple #4
0
 /// <summary>
 /// Remove a give category object.
 /// </summary>
 ///
 /// <param name="category">category object</param>
 ///
 /// <returns>true if the category was removed</returns>
 public bool removeCategory(PCategory category)
 {
     return(this.categories.Remove(category));
 }
Exemple #5
0
 /// <summary>
 /// Adds the specified category into the rank.
 /// </summary>
 ///
 /// <param name="category">PCategory object to add to the rank</param>
 public void addCategory(PCategory category)
 {
     this.categories.Add(category);
 }
Exemple #6
0
        /// <summary>
        /// Deserializes XML into KStructure object
        /// </summary>
        ///
        /// <param name="doc">XDocument instance</param>
        ///
        /// <returns>KStructure object</returns>
        public KStructure createKStructure(XDocument doc)
        {
            // [TODO] validate against schema

            XName[] nodeNames;

            // [SC] a hash table of all categories
            Dictionary <string, PCategory> categories = new Dictionary <string, PCategory>();

            // [SC] a hash table of all states
            Dictionary <string, KState> states = new Dictionary <string, KState>();

            // [SC] iterate through 'TwoA/PCategories/PCategory' elements
            nodeNames = new XName[] { XMLFactory.PCATS_ELEM, XMLFactory.PCAT_ELEM };
            foreach (XElement categoryElem in SelectNodes(doc.Root, nodeNames))
            {
                // [SC] get the value of 'TwoA/PCategories/PCategory@xsd:id' attribute
                string id = categoryElem.Attribute(XMLFactory.ID_ATTR).Value;

                // [SC] get the value of 'TwoA/PCategories/PCategory/Rating' element
                double rating;
                if (!Double.TryParse(categoryElem.Element(XMLFactory.RATING_ELEM).Value, out rating))
                {
                    Log(Severity.Error, String.Format("createKStructure: unable to parse rating for category {0}. Returning null.", id));
                    return(null); // [TODO] no need due to schema check?
                }

                PCategory category = new PCategory(id, rating);

                categories.Add(id, category);
            }

            RankOrder rankOrder = new RankOrder();

            // [SC] parse the value of 'TwoA/RankOrder/Params/Threshold' element
            nodeNames = new XName[] { XMLFactory.RANKORDER_ELEM, XMLFactory.PARAMS_ELEM, XMLFactory.THRESHOLD_ELEM };
            double threshold;

            if (Double.TryParse(SelectSingleNode(doc.Root, nodeNames).Value, out threshold))
            {
                rankOrder.Threshold = threshold;
            }
            else
            {
                Log(Severity.Error, "createKStructure: unable to parse the threshold value. Returning null value. Returning null.");
                return(null); // [TODO] no need due to schema check?
            }

            // [SC] iterate through 'TwoA/RankOrder/Ranks/Rank' elements
            nodeNames = new XName[] { XMLFactory.RANKORDER_ELEM, XMLFactory.RANKS_ELEM, XMLFactory.RANK_ELEM };
            foreach (XElement rankElem in SelectNodes(doc.Root, nodeNames))
            {
                Rank rank = new Rank();

                // [SC] parse the value of 'TwoA/RankOrder/Ranks/Rank@Index' atttribute
                int rankIndex;
                if (Int32.TryParse(rankElem.Attribute(XMLFactory.INDEX_ATTR).Value, out rankIndex))
                {
                    rank.RankIndex = rankIndex;
                }
                else
                {
                    Log(Severity.Error, "createKStructure: unable to parse the index of a rank in the rank order. Returning null.");
                    return(null); // [TODO] no need due to schema check?
                }

                // [SC] iterate through 'TwoA/RankOrder/Ranks/Rank/PCategory' elements
                foreach (XElement categoryElem in rankElem.Elements(XMLFactory.PCAT_ELEM))
                {
                    // [SC] parse 'TwoA/RankOrder/Ranks/Rank/PCategory@xsd:idref' attribute
                    if (categoryElem.Attribute(XMLFactory.IDREF_ATTR) == null)
                    {
                        Log(Severity.Error, String.Format("createKStructure: unable to parse ID for a category in rank {0} of the rank order. Returning null.", rankIndex));
                        return(null); // [TODO] no need due to schema check?
                    }
                    string id = categoryElem.Attribute(XMLFactory.IDREF_ATTR).Value;

                    // [SC] retrieve PCategory object by its id and add it to the rank object
                    PCategory category = categories[id];
                    if (category == null)
                    {
                        Log(Severity.Error
                            , String.Format("createKStructure: category {0} from rank {1} of rank order is not found in the list of categories. Returning null."
                                            , id, rankIndex));
                        return(null); // [TODO] no need due to schema check?
                    }
                    rank.addCategory(category);
                }

                rankOrder.addRank(rank);
            }

            KStructure kStructure = new KStructure(rankOrder);

            // [SC] iterate through 'TwoA/KStructure/KSRank' elements
            nodeNames = new XName[] { XMLFactory.KSTRUCTURE_ELEM, XMLFactory.KSRANK_ELEM };
            foreach (XElement ksrankElem in SelectNodes(doc.Root, nodeNames))
            {
                KSRank ksrank = new KSRank();

                // [SC] parse the value of 'TwoA/KStructure/KSRank@Index' attribute
                int rankIndex;
                if (Int32.TryParse(ksrankElem.Attribute(XMLFactory.INDEX_ATTR).Value, out rankIndex))
                {
                    ksrank.RankIndex = rankIndex;
                }
                else
                {
                    Log(Severity.Error, "createKStructure: unable to parse index of a rank in the knowledge structure. Returning null.");
                    return(null); // [TODO] no need due to schema check?
                }


                if (rankIndex == 0)
                {
                    XElement rootStateElem = ksrankElem.Element(XMLFactory.KSTATE_ELEM);

                    // [SC] parse 'TwoA/KStructure/KSRank/KState@xsd:id' attribute
                    if (rootStateElem.Attribute(XMLFactory.ID_ATTR) == null)
                    {
                        Log(Severity.Error, "createKStructure: unable to parse ID of the root state in the knowledge structure. Returning null.");
                        return(null); // [TODO] no need due to schema check?
                    }
                    ksrank.getStateAt(0).Id = rootStateElem.Attribute(XMLFactory.ID_ATTR).Value;

                    states.Add(ksrank.getStateAt(0).Id, ksrank.getStateAt(0));

                    kStructure.addRank(ksrank);

                    continue;
                }

                // [SC] iterate through 'TwoA/KStructure/KSRank/KState' elements
                foreach (XElement stateElem in ksrankElem.Elements(XMLFactory.KSTATE_ELEM))
                {
                    KState kstate = new KState();

                    // [SC] parse 'TwoA/KStructure/KSRank/KState@xsd:id' attribute
                    if (stateElem.Attribute(XMLFactory.ID_ATTR) == null)
                    {
                        Log(Severity.Error, String.Format("createKStructure: unable to parse ID of a state in the rank {0} of the knowledge structure. Returning null.", rankIndex));
                        return(null); // [TODO] no need due to schema check?
                    }
                    kstate.Id = stateElem.Attribute(XMLFactory.ID_ATTR).Value;

                    // [SC] parse 'TwoA/KStructure/KSRank/KState@Type' attribute
                    if (stateElem.Attribute(XMLFactory.TYPE_ATTR) == null)
                    {
                        Log(Severity.Error, String.Format("createKStructure: unable to parse state type in the rank {0} of the knowledge structure. Returning null.", rankIndex));
                        return(null); // [TODO] no need due to schema check?
                    }
                    kstate.StateType = stateElem.Attribute(XMLFactory.TYPE_ATTR).Value;

                    // [SC] iterate through 'TwoA/KStructure/KSRank/KState/PCategories/PCategory' elements
                    nodeNames = new XName[] { XMLFactory.PCATS_ELEM, XMLFactory.PCAT_ELEM };
                    foreach (XElement categoryElem in SelectNodes(stateElem, nodeNames))
                    {
                        // [SC] parse 'TwoA/KStructure/KSRank/KState/PCategories/PCategory@xsd:idref' attribute
                        if (categoryElem.Attribute(XMLFactory.IDREF_ATTR) == null)
                        {
                            Log(Severity.Error, String.Format("createKStructure: unable to parse ID of a category in the state {0}. Returning null.", kstate.Id));
                            return(null); // [TODO] no need due to schema check?
                        }
                        string id = categoryElem.Attribute(XMLFactory.IDREF_ATTR).Value;

                        // [SC] retrieve PCategory object by its id and add it to the rank object
                        PCategory category = categories[id];
                        if (category == null)
                        {
                            Log(Severity.Error
                                , String.Format("createKStructure: category {0} from the state {1} is not found in the list of categories. Returning null."
                                                , id, kstate.Id));
                            return(null); // [TODO] no need due to schema check?
                        }
                        kstate.addCategory(category);
                    }

                    // [SC] iterate through 'TwoA/KStructure/KSRank/KState/PreviousStates/KState' elements
                    nodeNames = new XName[] { XMLFactory.PREV_STATES_ELEM, XMLFactory.KSTATE_ELEM };
                    foreach (XElement prevStateElem in SelectNodes(stateElem, nodeNames))
                    {
                        // [SC] parse 'TwoA/KStructure/KSRank/KState/PreviousStates/KState@xsd:idref' attribute
                        if (prevStateElem.Attribute(XMLFactory.IDREF_ATTR) == null)
                        {
                            Log(Severity.Error, String.Format("createKStructure: unable to parse ID of a previous state for a state {0}. Returning null.", kstate.Id));
                            return(null); // [TODO] no need due to schema check?
                        }
                        string id = prevStateElem.Attribute(XMLFactory.IDREF_ATTR).Value;

                        // [SC] retrieve prev state object by its id and add it to the current state object
                        KState prevState = states[id];
                        if (prevState == null)
                        {
                            Log(Severity.Error, String.Format("createKStructure: unable to find previously created state object with id '{0}'. Returning null.", id));
                            return(null); // [TODO] no need due to schema check?
                        }
                        kstate.addPrevState(prevState);
                        prevState.addNextState(kstate);
                    }

                    states.Add(kstate.Id, kstate);
                    ksrank.addState(kstate);
                }

                kStructure.addRank(ksrank);
            }

            return(kStructure);
        }
Exemple #7
0
        /// <summary>
        /// creates an XML document object from a given KStructure object
        /// </summary>
        ///
        /// <param name="kStructure">KStructure object with a rank order and knowledge structure</param>
        ///
        /// <returns>XmlDocument object</returns>
        public XDocument createXml(KStructure kStructure)
        {
            // [SC] verifying that KStructure object is not null
            if (kStructure == null)
            {
                Log(Severity.Error, "Unable to transform knowledge structure into XML format. kStructure parameter is null. Returning null.");
                return(null);
            }

            // [SC] create xml document object
            XDocument doc = new XDocument();

            // [SC] add xml declaration to the document
            doc.Declaration = new XDeclaration("1.0", "UTF-8", "yes");

            // [SC] add a root element 'TwoA' and declare namespace attributes
            XElement twoAElem = new XElement(XMLFactory.TWOA_ELEM
                                             , new XAttribute(XMLFactory.XMLNS_ATTR, XMLFactory.twoa)
                                             , new XAttribute(XMLFactory.XSD_ATTR, XMLFactory.xsd)
                                             );

            doc.Add(twoAElem);

            // [SC] create a list of categories and a rank order
            if (kStructure.hasRankOrder())
            {
                RankOrder rankOrder = kStructure.rankOrder;
                rankOrder.sortAscending();

                // [SC] add 'TwoA/PCategories' list element
                XElement pcatsElem = new XElement(XMLFactory.PCATS_ELEM);
                twoAElem.Add(pcatsElem);

                // [SC] add 'TwoA/RankOrder' element
                XElement rankOrderElem = new XElement(XMLFactory.RANKORDER_ELEM);
                twoAElem.Add(rankOrderElem);

                // [SC] add 'TwoA/RankOrder/Params' list element
                XElement rankParamsElem = new XElement(XMLFactory.PARAMS_ELEM);
                rankOrderElem.Add(rankParamsElem);

                // [SC] add 'TwoA/RankOrder/Params.Threshold' element
                XElement thresholdElem = new XElement(XMLFactory.THRESHOLD_ELEM);
                rankParamsElem.Add(thresholdElem);
                thresholdElem.SetValue("" + rankOrder.Threshold);

                // [SC] create 'TwoA/RankOrder/Ranks' list element
                XElement ranksElem = new XElement(XMLFactory.RANKS_ELEM);
                rankOrderElem.Add(ranksElem);

                // [SC] iterate through ranks and create correspoinding XML elements
                for (int rankCounter = 0; rankCounter < rankOrder.getRankCount(); rankCounter++)
                {
                    Rank rank = rankOrder.getRankAt(rankCounter);

                    // [SC] add 'TwoA/RankOrder/Ranks/Rank' element
                    XElement rankElem = new XElement(XMLFactory.RANK_ELEM);
                    ranksElem.Add(rankElem);
                    // [SC] add 'TwoA/RankOrder/Ranks/Rank@Index' attribute to the 'Rank' element
                    XAttribute indexAttr = new XAttribute(XMLFactory.INDEX_ATTR, "" + rank.RankIndex);
                    rankElem.Add(indexAttr);

                    // [SC] interate through categories in the rank and create corresponding XML element and reference to it
                    for (int catCounter = 0; catCounter < rank.getCategoryCount(); catCounter++)
                    {
                        PCategory pcat = rank.getCategoryAt(catCounter);

                        // [SC] add 'TwoA/PCategories/PCategory' element with 'xsd:id' attribute
                        XElement pcatElem = new XElement(XMLFactory.PCAT_ELEM);
                        pcatsElem.Add(pcatElem);
                        // [SC] add 'TwoA/PCategories/PCategory@xsd:id' attribute
                        XAttribute idAttr = new XAttribute(XMLFactory.ID_ATTR, "" + pcat.Id);
                        pcatElem.Add(idAttr);
                        // [SC] add 'TwoA/PCategories/PCategory/Rating' element
                        XElement ratingElem = new XElement(XMLFactory.RATING_ELEM);
                        pcatElem.Add(ratingElem);
                        ratingElem.SetValue("" + pcat.Rating);

                        // [SC] add 'TwoA/RankOrder/Ranks/Rank/PCategory' element with 'xsd:idref' attribute
                        XElement pcatRefElem = new XElement(XMLFactory.PCAT_ELEM);
                        rankElem.Add(pcatRefElem);
                        // [SC] add 'TwoA/RankOrder/Ranks/Rank/PCategory@xsd:idref' attribute
                        XAttribute idrefAttr = new XAttribute(XMLFactory.IDREF_ATTR, "" + pcat.Id);
                        pcatRefElem.Add(idrefAttr);
                    }
                }
            }
            else
            {
                Log(Severity.Warning, "Rank order is missing while transforming KStructure object into XML format.");
            }

            // [SC] creates elements for 'KStructure'
            if (kStructure.hasRanks())
            {
                kStructure.sortAscending();

                // [SC] add 'TwoA/KStructure' element
                XElement kStructureElem = new XElement(XMLFactory.KSTRUCTURE_ELEM);
                twoAElem.Add(kStructureElem);

                // [SC] iterate through KSRanks and create corresponding XML elements
                for (int rankCounter = 0; rankCounter < kStructure.getRankCount(); rankCounter++)
                {
                    KSRank rank = kStructure.getRankAt(rankCounter);

                    // [SC] add 'TwoA/KStructure/KSRank' element
                    XElement ksRankElem = new XElement(XMLFactory.KSRANK_ELEM);
                    kStructureElem.Add(ksRankElem);
                    // [SC] add 'TwoA/KStructure/KSRank@Index' attribute
                    XAttribute indexAttr = new XAttribute(XMLFactory.INDEX_ATTR, "" + rank.RankIndex);
                    ksRankElem.Add(indexAttr);


                    // [SC] iterate through states and add corresponding XML elements
                    for (int stateCounter = 0; stateCounter < rank.getStateCount(); stateCounter++)
                    {
                        KState state = rank.getStateAt(stateCounter);

                        // [SC] add 'TwoA/KStructure/KSRank/KState' element with 'xsd:id' attribute
                        XElement stateElem = new XElement(XMLFactory.KSTATE_ELEM);
                        ksRankElem.Add(stateElem);
                        // [SC] add 'TwoA/KStructure/KSRank/KState@xsd:id' attribute
                        XAttribute idAttr = new XAttribute(XMLFactory.ID_ATTR, "" + state.Id);
                        stateElem.Add(idAttr);
                        // [SC] add 'TwoA/KStructure/KSRank/KState@Type' attribute
                        XAttribute typeAttr = new XAttribute(XMLFactory.TYPE_ATTR, "" + state.StateType);
                        stateElem.Add(typeAttr);

                        // [SC] add 'TwoA/KStructure/KSRank/KState/PCategories' list element
                        XElement pcatsElem = new XElement(XMLFactory.PCATS_ELEM);
                        stateElem.Add(pcatsElem);

                        // [SC] iterate through categories in the state
                        for (int catCounter = 0; catCounter < state.getCategoryCount(); catCounter++)
                        {
                            PCategory pcat = state.getCategoryAt(catCounter);

                            // [SC] add 'TwoA/KStructure/KSRank/KState/PCategories/PCategory' element with 'xsd:idref' attribute
                            XElement pcatElem = new XElement(XMLFactory.PCAT_ELEM);
                            pcatsElem.Add(pcatElem);
                            // [SC] add 'TwoA/KStructure/KSRank/KState/PCategories/PCategory@xsd:idref' attribute
                            XAttribute idrefAttr = new XAttribute(XMLFactory.IDREF_ATTR, "" + pcat.Id);
                            pcatElem.Add(idrefAttr);
                        }

                        // [SC] add 'TwoA/KStructure/KSRank/KState/PreviousStates' list element
                        XElement prevStatesElem = new XElement(XMLFactory.PREV_STATES_ELEM);
                        stateElem.Add(prevStatesElem);

                        // [SC] iterate through immediate prerequisite states in the gradient
                        for (int prevStateCounter = 0; prevStateCounter < state.getPrevStateCount(); prevStateCounter++)
                        {
                            KState prevState = state.getPrevStateAt(prevStateCounter);

                            // [SC] add 'TwoA/KStructure/KSRank/KState/PreviousStates/KState' element with 'xsd:idref' attribute
                            XElement prevStateElem = new XElement(XMLFactory.KSTATE_ELEM);
                            prevStatesElem.Add(prevStateElem);
                            // [SC] add 'TwoA/KStructure/KSRank/KState/PreviousStates/KState@xsd:idref' attribute
                            XAttribute idrefAttr = new XAttribute(XMLFactory.IDREF_ATTR, "" + prevState.Id);
                            prevStateElem.Add(idrefAttr);
                        }

                        // [SC] add 'TwoA/KStructure/KSRank/KState/NextStates' list element
                        XElement nextStatesElem = new XElement(XMLFactory.NEXT_STATES_ELEM);
                        stateElem.Add(nextStatesElem);

                        // [SC] iterate through immediate next states in the gradient
                        for (int nextStateCounter = 0; nextStateCounter < state.getNextStateCount(); nextStateCounter++)
                        {
                            KState nextState = state.getNextStateAt(nextStateCounter);

                            // [SC] add 'TwoA/KStructure/KSRank/KState/NextStates/KState' element with 'xsd:idref' attribute
                            XElement nextStateElem = new XElement(XMLFactory.KSTATE_ELEM);
                            nextStatesElem.Add(nextStateElem);
                            // [SC] add 'TwoA/KStructure/KSRank/KState/NextStates/KState@xsd:idref' attribute
                            XAttribute idrefAttr = new XAttribute(XMLFactory.IDREF_ATTR, "" + nextState.Id);
                            nextStateElem.Add(idrefAttr);
                        }
                    }
                }
            }
            else
            {
                Log(Severity.Warning, "Knowledge structure is missing while transforming KStructure object into XML format.");
            }

            return(doc);
        }
 /// <summary>
 /// returns true if this category has the same Id as the category passed as a parameter
 /// </summary>
 ///
 /// <param name="category">another category to compare to</param>
 ///
 /// <returns>a boolean value</returns>
 public bool isSameId(PCategory category)
 {
     return(this.isSameId(category.Id));
 }