Example #1
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>
        /// Generates a knowledge structure (KStructure object) from a ranked order (RankOrder object) by applying Rule 1.
        /// </summary>
        ///
        /// <param name="rankOrder">RankOrder object that is used to generate a knowledge structure.</param>
        ///
        /// <returns>KStructure object, or null if error occured.</returns>
        public KStructure createKStructure(RankOrder rankOrder)
        {
            // Implements Rule 1: Given a set GR of problems with a rank R and a set G<R of problems of lower ranks,
            // a union of any subset of GR with G<R is a knowledge state.

            // [SC] make sure the rankOrder object is not null
            if (rankOrder == null)
            {
                Log(Severity.Error, "createKStructure: Null object is passed as RankOrder parameter. Returning null.");
                return(null);
            }

            // [SC] make sure there is at least one rank in the rank order
            if (rankOrder.getRankCount() == 0)
            {
                Log(Severity.Error, "createKStructure: rank order has no ranks. Returning null.");
                return(null);
            }

            // [SC] make sure the ranks are sorted in an ascending order
            rankOrder.sortAscending();

            // [SC] creating knowledge states
            List <KState>    allStates      = new List <KState>();
            List <PCategory> prevCategories = new List <PCategory>();

            foreach (Rank rank in rankOrder.getRanks())
            {
                // [SC] getting all unique subsets of categories in this rank
                List <List <PCategory> > subsets = rank.getSubsets();

                // [SC] for each subset, create a knowledge state by combining with all categories of lower ranks
                foreach (List <PCategory> subset in subsets)
                {
                    KState state = new KState();
                    foreach (PCategory category in prevCategories)
                    {
                        state.addCategory(category);
                    }
                    foreach (PCategory category in subset)
                    {
                        state.addCategory(category);
                    }
                    allStates.Add(state);
                }

                prevCategories.AddRange(rank.getCategories());
            }

            // [SC] sort states by their sizes in an ascending order
            allStates.Sort((stateOne, stateTwo) => stateOne.getCategoryCount().CompareTo(stateTwo.getCategoryCount()));

            // [SC] creating an empty knowledge structure object
            KStructure ks = new KStructure(rankOrder);

            // [SC] creating 0th rank with an empty root state
            int    rankIndex    = 0;
            int    stateCounter = 0;                     // [SC] used to generate an ID for each state
            KSRank prevRank     = null;
            KSRank currRank     = new KSRank(rankIndex); // [SC] the root rank will automatically add an empty root state

            ks.addRank(currRank);

            // [SC] adding all states in respective ranks
            foreach (KState state in allStates)
            {
                if (state.getCategoryCount() > rankIndex)
                {
                    stateCounter = 0;
                    prevRank     = currRank;
                    currRank     = new KSRank(++rankIndex);
                    ks.addRank(currRank);
                }

                if (currRank.addState(state))
                {
                    state.Id = KSGenerator.getStateID(rankIndex, ++stateCounter);

                    foreach (KState prevState in prevRank.getStates())
                    {
                        if (prevState.isSubsetOf(state))
                        {
                            prevState.addNextState(state);
                            state.addPrevState(prevState);
                        }
                    }
                }
            }

            return(ks);
        }