cz.cuni.mff.ms.brodecva.botnicek.ide.compile.library.Randomize.java Source code

Java tutorial

Introduction

Here is the source code for cz.cuni.mff.ms.brodecva.botnicek.ide.compile.library.Randomize.java

Source

/**
 * Copyright Vclav Brodec 2014.
 * 
 * This file is part of Botn?ek.
 * 
 * Botn?ek is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Botn?ek is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Botn?ek.  If not, see <http://www.gnu.org/licenses/>.
 */
package cz.cuni.mff.ms.brodecva.botnicek.ide.compile.library;

import java.util.Arrays;
import java.util.List;

import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ContiguousSet;
import com.google.common.collect.DiscreteDomain;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Range;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;

import cz.cuni.mff.ms.brodecva.botnicek.ide.aiml.elements.category.Template;
import cz.cuni.mff.ms.brodecva.botnicek.ide.aiml.elements.template.TemplateElement;
import cz.cuni.mff.ms.brodecva.botnicek.ide.aiml.elements.template.implementations.Random;
import cz.cuni.mff.ms.brodecva.botnicek.ide.aiml.elements.template.implementations.Srai;
import cz.cuni.mff.ms.brodecva.botnicek.ide.aiml.elements.template.implementations.Star;
import cz.cuni.mff.ms.brodecva.botnicek.ide.aiml.elements.template.implementations.Text;
import cz.cuni.mff.ms.brodecva.botnicek.ide.aiml.elements.toplevel.Category;
import cz.cuni.mff.ms.brodecva.botnicek.ide.aiml.elements.toplevel.Topic;
import cz.cuni.mff.ms.brodecva.botnicek.ide.aiml.types.NormalWord;
import cz.cuni.mff.ms.brodecva.botnicek.ide.aiml.types.Patterns;
import cz.cuni.mff.ms.brodecva.botnicek.ide.design.system.model.NamingAuthority;
import cz.cuni.mff.ms.brodecva.botnicek.library.platform.AIML;
import cz.cuni.mff.ms.brodecva.botnicek.library.platform.AIMLIndex;

/**
 * <p>
 * Knihovna s tmatem pro nhodn uspodn stav ze vstupu na zsobnk.
 * </p>
 * <p>
 * Na zsobnk umst pouze jednu kopii, ale po?et opakovn na vstupu ovlivuje
 * pravdpodobnost vskytu na dan vsledn pozici.
 * </p>
 * 
 * @author Vclav Brodec
 * @version 1.0
 */
public class Randomize {
    private static final String RANDOM_START = "RANDOMSTART";
    private static final String RANDOM_END = "RANDOMEND";
    private static final String REMOVE_START = "REMOVESTART";
    private static final String REMOVE_END = "REMOVEEND";

    private static List<List<TemplateElement>> createChoices(final int starsCount) {
        final ImmutableList.Builder<List<TemplateElement>> builder = ImmutableList.builder();

        final String space = AIML.WORD_DELIMITER.getValue();
        final String randomStart = RANDOM_START;
        final String randomEnd = RANDOM_END;

        final ImmutableSortedSet<Integer> set = ContiguousSet.create(Range.closed(1, starsCount),
                DiscreteDomain.integers());

        for (int picked = 1; picked <= starsCount; picked++) {
            final Star pickedStar = Star.create(new AIMLIndex(picked));
            final SetView<Integer> rest = Sets.difference(set, ImmutableSet.of(picked));

            // @formatter:off
            // <li><star index="3"/> <srai>RANDOMSTART <srai>REMOVESTART <star index="3"/> <star index="1"/> <star index="2"/> <star index="4"/> REMOVEEND</srai> RANDOMEND</srai><li>
            builder.add(ImmutableList.<TemplateElement>of(pickedStar, Text.create(space),
                    Srai.create(Text.create(randomStart + space), Srai.create(removeCopies(pickedStar, rest)),
                            Text.create(space + randomEnd))));
            // @formatter:on
        }

        return builder.build();
    }

    private static String createStars(final int starsCount) {
        final String[] stars = new String[starsCount];
        Arrays.fill(stars, AIML.STAR_WILDCARD.getValue());

        return Joiner.on(AIML.WORD_DELIMITER.getValue()).join(stars);
    }

    /**
     * Vrt seznam s jednm tmatem (vpo?et v jeho rmci je een pomoc
     * manipulac vzoru s krajnmi zarkami, tud nen nutn rezervovat dal
     * stavy), kter pi pechodu do nj a uvozenm vstupu ze stav jeho nzvem
     * uspod nhodn stavy na zsobnk (?m vce je kopi danho stavu, tm
     * vt m anci na umstn ble k vrcholu zsobnku).
     * 
     * @param randomizeState
     *            nzev stavu pro promchn
     * @param maxPriority
     *            maximln povolen priorita hrany
     * @param maxBranchFactor
     *            maximln po?et odchozch hran z uzlu
     * @param statesNamesAuthority
     *            autorita obsahujc vechny pouit nzvy stav
     * @return tma
     */
    public static List<Topic> getLibrary(final NormalWord randomizeState, final int maxPriority,
            final int maxBranchFactor, final NamingAuthority statesNamesAuthority) {
        Preconditions.checkNotNull(randomizeState);
        Preconditions.checkNotNull(statesNamesAuthority);
        Preconditions.checkArgument(maxPriority >= 0);
        Preconditions.checkArgument(maxBranchFactor >= 0);

        final String randomize = randomizeState.getText();
        final String star = AIML.STAR_WILDCARD.getValue();
        final String space = AIML.WORD_DELIMITER.getValue();

        final ImmutableList.Builder<Category> categories = ImmutableList.builder();

        shuffle(maxPriority, maxBranchFactor, randomizeState, categories);
        removeAll(statesNamesAuthority, categories);

        // @formatter:off
        //      <topic name="RANDOMIZE *">
        // @formatter:on
        return ImmutableList
                .of(Topic.create(Patterns.create(Joiner.on(space).join(randomize, star)), categories.build()));
    }

    private static String join(final String... parts) {
        return Joiner.on(AIML.WORD_DELIMITER.getValue()).join(parts);
    }

    /**
     * <p>
     * Vytvo kd pro odebrn vech vskyt prvku ze seznamu (to jsou v tomto
     * ppad ostatn mchan prvky).
     * </p>
     * <p>
     * Bohuel predikty jazyka AIML nelze porovnvat mezi sebou, ale jen v?i
     * vzoru, proto je nutn vytvoit pro kad pouit stav (sta?ily by ovem
     * jen odchoz hrany nhodnch uzl!!!) vlastn kopii procedury.
     * </p>
     */
    private static void removeAll(final NamingAuthority statesNamesAuthority, final Builder<Category> categories) {
        final java.util.Set<String> allStates = statesNamesAuthority.getSnapshot();

        for (final String state : allStates) {
            removeAllForState(state, categories);
        }
    }

    private static void removeAllForState(final String state, final Builder<Category> categories) {
        final String space = AIML.WORD_DELIMITER.getValue();
        final String star = AIML.STAR_WILDCARD.getValue();
        final String removeStart = REMOVE_START;
        final String removeEnd = REMOVE_END;

        // @formatter:off
        //    <category>
        //        <pattern>REMOVESTART A A * REMOVEEND</pattern>
        //        <that>*</that>
        //        <template><srai>REMOVESTART A <star/> REMOVEEND</srai></template>
        //    </category>
        categories.add(Category.create(Patterns.create(join(removeStart, state, state, star, removeEnd)),
                Patterns.createUniversal(),
                Template.create(Srai.create(Text.create(join(removeStart, state) + space), Star.create(),
                        Text.create(space + removeEnd)))));

        //    <category>
        //        <pattern>REMOVESTART A * * REMOVEEND</pattern>
        //        <that>*</that>
        //        <template><star index="1"> <srai>REMOVESTART A <star index="2"> REMOVEEND</srai></template>
        //    </category>
        categories.add(Category.create(Patterns.create(join(removeStart, state, star, star, removeEnd)),
                Patterns.createUniversal(),
                Template.create(Star.create(new AIMLIndex(1)), Text.create(space),
                        Srai.create(Text.create(join(removeStart, state) + space), Star.create(new AIMLIndex(2)),
                                Text.create(space + removeEnd)))));

        //    <category>
        //        <pattern>REMOVESTART A A REMOVEEND</pattern>
        //        <that>*</that>
        //        <template></template>
        //    </category>
        categories.add(Category.create(Patterns.create(join(removeStart, state, state, removeEnd)),
                Patterns.createUniversal(), Template.create()));

        //    <category>
        //        <pattern>REMOVESTART A * REMOVEEND</pattern>
        //        <that>*</that>
        //        <template><star/></template>
        //    </category>
        categories.add(Category.create(Patterns.create(join(removeStart, state, star, removeEnd)),
                Patterns.createUniversal(), Template.create(Star.create())));
        // @formatter:on
    }

    private static List<TemplateElement> removeCopies(final Star pickedStar, final SetView<Integer> rest) {
        final String space = AIML.WORD_DELIMITER.getValue();
        final String removeStart = REMOVE_START;
        final String removeEnd = REMOVE_END;

        final ImmutableList.Builder<TemplateElement> removeCode = ImmutableList.builder();

        // @formatter:off
        // REMOVESTART <star index="3"/> <star index="1"/> <star index="2"/> <star index="4"/> REMOVEEND
        // @formatter:on
        removeCode.add(Text.create(removeStart + space));
        removeCode.add(pickedStar);
        for (final int other : rest) {
            removeCode.add(Text.create(space));
            removeCode.add(Star.create(new AIMLIndex(other)));
        }
        removeCode.add(Text.create(space + removeEnd));

        return removeCode.build();
    }

    /**
     * Vynsob maximln prioritu a vtvc faktor, vytvo podle vsledku
     * pslun po?et zachytvacch olk, pi vpo?tu se pak dky prvku
     * nhoda vybere jedno zachycen slovo a ped na vstup, to se dle smae
     * ze zbylch a zbytek se rekurzivn zpracuje.
     */
    private static void shuffle(final int maxPriority, final int maxBranchFactor, final NormalWord randomizeState,
            final ImmutableList.Builder<Category> categories) {
        final String randomize = randomizeState.getText();
        final String randomStart = RANDOM_START;
        final String randomEnd = RANDOM_END;
        final String star = AIML.STAR_WILDCARD.getValue();
        final String space = AIML.WORD_DELIMITER.getValue();

        // @formatter:off
        //    <category>
        //        <pattern>RANDOMIZE *</pattern>
        //        <that>*</that>
        //        <template><srai>RANDOMSTART <star/> RANDOMEND</srai></template>
        //    </category>
        categories.add(Category.create(Patterns.create(join(randomize, star)), Patterns.createUniversal(),
                Template.create(Srai.create(Text.create(randomStart + space), Star.create(),
                        Text.create(space + randomEnd)))));

        //    <category>
        //        <pattern>RANDOMSTART RANDOMEND</pattern>
        //        <that>*</that>
        //        <template></template>
        //    </category>
        categories.add(Category.create(Patterns.create(join(randomStart, randomEnd)), Patterns.createUniversal(),
                Template.create()));

        //    <category>
        //        <pattern>RANDOMSTART * RANDOMEND</pattern>
        //        <that>*</that>
        //        <template><star/></template>
        //    </category>
        categories.add(Category.create(Patterns.create(join(randomStart, star, randomEnd)),
                Patterns.createUniversal(), Template.create(Star.create())));

        //    <category>
        //        <pattern>RANDOMSTART * * * * RANDOMEND</pattern>
        //        <that>*</that>
        //        <template><random>
        //            ...
        //            <li><star index="3"/> <srai>RANDOMSTART <srai>REMOVESTART <star index="3"/> <star index="1"/> <star index="2"/> <star index="4"/> REMOVEEND</srai> RANDOMEND</srai><li>
        //            ...
        //            </random></template>
        //    </category>
        //    ...
        final int maxStarsCount = maxPriority * maxBranchFactor;
        for (int starsCount = 2; starsCount <= maxStarsCount; starsCount++) {
            categories.add(Category.create(Patterns.create(join(randomStart, createStars(starsCount), randomEnd)),
                    Patterns.createUniversal(), Template.create(Random.create(createChoices(starsCount)))));
        }
        // @formatter:on
    }

    private Randomize() {
    }
}