switch(option.getOption().getValueCardinality()) {
                    case REQUIRED:
                        buffer0.append(" ");
                        buffer0.append(valueName);
                        break;
                    case OPTIONAL:
                        buffer0.append(" [");
                        buffer0.append(valueName);
                        buffer0.append("]");
                        break;
                    case NONE:
                    default:
                }

/*
 * $Id$
 *
 * SARL is an general-purpose agent programming language.
 * More details on http://www.sarl.io
 *
 *
 */
package io.sarl.maven.bootiqueapp.mdhelp;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.google.inject.Injector;
import io.bootique.cli.Cli;
import io.bootique.command.CommandOutcome;
import io.bootique.command.CommandWithMetadata;
import io.bootique.help.HelpOption;
import io.bootique.help.HelpOptions;
import io.bootique.meta.application.ApplicationMetadata;
import io.bootique.meta.application.CommandMetadata;
import io.sarl.lang.util.CliUtilities;

/**
 * Command for displaying the help on the standard output using a Markdown format.
 *
 * @author $Author: sgalland$
 * @version $FullVersion$
 * @mavengroupid $GroupId$
 * @mavenartifactid $ArtifactId$
 * @since 0.12
 */
public class GenerateMarkdownHelpCommand extends CommandWithMetadata {

    private static final String CLI_NAME = "generatemarkdownhelp";

    private static final String PIPE = "|";

    private final Injector injector;

    /**
     * Constructor.
     *
     * @param injector the injector to be used.
     */
    public GenerateMarkdownHelpCommand(Injector injector) {
        this(injector, GenerateMarkdownHelpCommand.class, Messages.GenerateMarkdownHelpCommand_0);
    }

    /**
     * Constructor.
     *
     * @param injector the injector to be used.
     * @param commandType the type of the command.
     * @param description the description of the command.
     */
    protected GenerateMarkdownHelpCommand(Injector injector, Class<? extends GenerateMarkdownHelpCommand> commandType, String description) {
        super(CommandMetadata.builder(commandType).description(description).name(CLI_NAME));
        this.injector = injector;
    }

    /**
     * Replies the list of command-line options that are defined inside the runtime injector.
     *
     * @param runtime the runtime injector.
     * @return the options.
     */
    public static List<HelpOption> getOptions(Injector runtime) {
        final ApplicationMetadata application = runtime.getInstance(ApplicationMetadata.class);
        final HelpOptions helpOptions = new HelpOptions();
        application.getCommands().forEach(c -> {
            helpOptions.add(c.asOption());
            c.getOptions().forEach(o -> helpOptions.add(o));
        });
        application.getOptions().forEach(o -> helpOptions.add(o));
        return helpOptions.getOptions();
    }

    /**
     * Replies the options of the program in the form of a matrix of strings of characters.
     * The replied value is a table with 2 columns: the options' names, and the options' descriptions.
     * Each line of the table is a different option.
     *
     * @param runtime the runtime injector.
     * @param replacePipes indicates if the pipe character must be replaced by its HTML equivalent character.
     * @return the options of the program as a matrix of strings.
     */
    public static List<List<String>> getOptionsAsStrings(Injector runtime, boolean replacePipes) {
        final List<HelpOption> options = getOptions(runtime);
        final List<List<String>> matrix = new ArrayList<>(options.size());
        for (final HelpOption option : options) {
            String valueName = option.getOption().getValueName();
            if (valueName == null || valueName.length() == 0) {
                valueName = "val";
            } else if (replacePipes) {
                valueName = valueName.replace("|", PIPE);
            }
            final StringBuilder buffer0 = new StringBuilder();
            if (option.isShortNameAllowed()) {
                buffer0.append("-");
                buffer0.append(String.valueOf(option.getOption().getShortName()));

            }
            if (option.isLongNameAllowed()) {
                if (option.isShortNameAllowed()) {
                    buffer0.append("<br>");
                }
                buffer0.append(CliUtilities.getCommandLineLongOptionPrefix());
                buffer0.append(option.getOption().getName());
                switch(option.getOption().getValueCardinality()) {
                    case REQUIRED:
                        buffer0.append("=");
                        buffer0.append(valueName);
                        break;
                    case OPTIONAL:
                        buffer0.append("[=");
                        buffer0.append(valueName);
                        buffer0.append("]");
                        break;
                    case NONE:
                    default:
                }
            }
            final StringBuilder buffer1 = new StringBuilder();
            final String description = option.getOption().getDescription();
            if (description != null) {
                String text = description.replaceAll("[ \t\n\r\f]+", " ");
                text = text.replace("<", "<");
                text = text.replace(">", ">");
                if (replacePipes) {
                    text = text.replace("|", PIPE);
                }
                buffer1.append(description);
            }
            matrix.add(Arrays.asList(buffer0.toString(), buffer1.toString()));
        }
        return matrix;
    }

    @Override
    public CommandOutcome run(Cli cli) {
        final List<List<String>> options = getOptionsAsStrings(this.injector, true);
        final StringBuilder content = new StringBuilder();
        for (final List<String> row : options) {
            boolean first = true;
            for (final String cell : row) {
                if (first) {
                    first = false;
                    content.append("| ");
                } else {
                    content.append(" | ");
                }
                content.append(cell);
            }
            content.append(" |\n");
        }
        System.out.println(content.toString());
        return CommandOutcome.succeeded();
    }
}


switch(mDirector.split(instance)) {
            case MISSING:
                return mLeftFraction * mLeft.predict(instance) + mRightFraction * mRight.predict(instance);
            case LEFT:
                return mLeft.predict(instance);
            case RIGHT:
            default:
                return mRight.predict(instance);
        }

/*
 *
 * Use of this source code is bound by the Real Time Genomics Limited Software Licence Agreement
 *
 * If you did not receive a license accompanying this file, a copy must first be obtained by email
 * from example@nnthink.com.  On downloading, using and/or continuing to use this source
 * be made from time to time by Real Time Genomics Limited.
 */
package com.rtg.ml;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import com.rtg.util.MathUtils;
import com.rtg.util.StringUtils;
import com.rtg.util.Utils;

/**
 * Implements a binary classification tree.
 */
public final class BinaryTreeClassifier implements PredictClassifier {

    static final int SERIAL_VERSION = 1;

    final BinarySplitter mDirector;

    final PredictClassifier mLeft;

    final PredictClassifier mRight;

    final double mLeftFraction;

    final double mRightFraction;

    /**
     * Constructs a binary tree. When the split criterion cannot decide which subtree to delegate to, a weighted sum is returned.
     * @param director the split criterion
     * @param left the classifier that operates on all instances passing to the left
     * @param right the classifier that operates on all instances passing to the right
     * @param leftFraction the proportion of weight to assign to predictions from the left
     */
    public BinaryTreeClassifier(BinarySplitter director, PredictClassifier left, PredictClassifier right, double leftFraction) {
        if (leftFraction < 0 || leftFraction > 1) {
            throw new IllegalArgumentException("Left fraction must be between 0 and 1");
        }
        if (left == null || right == null) {
            throw new NullPointerException("Left and right trees must not be null");
        }
        mDirector = director;
        mLeft = left;
        mRight = right;
        mLeftFraction = leftFraction;
        mRightFraction = 1.0 - leftFraction;
    }

    /**
     * load a classifier from the stream
     * @param dis the stream to load from
     * @param data set of attributes for encoding/decoding values
     * @throws IOException if an IO error occurs
     */
    public BinaryTreeClassifier(DataInputStream dis, Dataset data) throws IOException {
        final int version = dis.readInt();
        if (version == 1) {
            mDirector = new BinarySplitter(dis, data);
            mLeft = MlPredictLoader.loadPredictClassifier(dis, data);
            mRight = MlPredictLoader.loadPredictClassifier(dis, data);
            mLeftFraction = dis.readDouble();
            mRightFraction = dis.readDouble();
        } else {
            throw new IOException("Unsupported tree version: " + version);
        }
    }

    @Override
    public void save(DataOutputStream dos, Dataset data) throws IOException {
        // tells loader which class to load
        dos.writeInt(MlPredictLoader.MlPredictType.BINARY_TREE.ordinal());
        dos.writeInt(SERIAL_VERSION);
        mDirector.save(dos, data);
        mLeft.save(dos, data);
        mRight.save(dos, data);
        dos.writeDouble(mLeftFraction);
        dos.writeDouble(mRightFraction);
    }

    @Override
    public double predict(double[] instance) {

    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null || !(obj instanceof BinaryTreeClassifier)) {
            return false;
        }
        final BinaryTreeClassifier obj1 = (BinaryTreeClassifier) obj;
        return mDirector.equals(obj1.mDirector) && mLeft.equals(obj1.mLeft) && mRight.equals(obj1.mRight) && MathUtils.approxEquals(mLeftFraction, obj1.mLeftFraction, 10e-10) && MathUtils.approxEquals(mRightFraction, obj1.mRightFraction, 10e-10);
    }

    @Override
    public int hashCode() {
        return Utils.pairHashContinuous(mDirector.hashCode(), mLeft.hashCode(), mRight.hashCode(), Double.valueOf(mLeftFraction).hashCode(), Double.valueOf(mRightFraction).hashCode());
    }

    @Override
    public StringBuilder toString(StringBuilder out, String indent, Dataset data) {
        out.append(indent).append(mDirector.toString(data)).append(StringUtils.LS);
        final String newIndent = indent + "  ";
        mLeft.toString(out, newIndent, data);
        mRight.toString(out, newIndent, data);
        return out;
    }
}