package expression.common; import base.ExtendedRandom; import java.util.List; import java.util.Map; /** * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) */ public class NodeRenderer { public static final String PAREN = "["; public static final List DEFAULT_PARENS = List.of(paren("(", ")")); public static final Mode MINI_MODE = Mode.SIMPLE_MINI; // Replace by TRUE_MINI for some challenge; public static final Settings FULL = Mode.FULL.settings(0); public static final Settings FULL_EXTRA = Mode.FULL.settings(Integer.MAX_VALUE / 4); public static final Settings SAME = Mode.SAME.settings(0); public static final Settings MINI = MINI_MODE.settings(0); public static final Settings TRUE_MINI = Mode.TRUE_MINI.settings(0); private final Renderer> renderer; private final Map brackets; private final ExtendedRandom random; public NodeRenderer( final Renderer> renderer, final Map brackets, final ExtendedRandom random ) { this.renderer = renderer; this.brackets = Map.copyOf(brackets); this.random = random; } public static Node paren(final boolean condition, final Node node) { return condition ? Node.op(PAREN, 1, node) : node; } public static Paren paren(final String open, final String close) { return new Paren(open, close); } public Node renderToNode(final Settings settings, final Expr expr) { final Expr> convert = expr.convert((name, variable) -> Node.op(name)); return renderer.render(convert, settings); } public String render(final Node node, final List parens) { return node.cata( String::valueOf, name -> name, (name, priority, arg) -> name == PAREN ? random.randomItem(parens).apply(arg) : priority == Integer.MAX_VALUE ? name + arg + brackets.get(name) : (priority & 1) == 1 ? name + arg : arg + name, (name, a, b) -> a + " " + name + " " + b ); } public String render(final Expr expr, final Settings settings) { return render(renderToNode(settings, expr), settings.parens()); } public enum Mode { FULL, SAME, TRUE_MINI, SIMPLE_MINI; public Settings settings(final int limit) { return new Settings(this, limit); } } public record Paren(String open, String close) { String apply(final String expression) { return open() + expression + close(); } } public record Settings(Mode mode, int limit, List parens) { public Settings(final Mode mode, final int limit) { this(mode, limit, DEFAULT_PARENS); } public Node extra(Node node, final ExtendedRandom random) { while (random.nextInt(Integer.MAX_VALUE) < limit) { node = paren(true, node); } return node; } public Settings withParens(final List parens) { return this.parens.equals(parens) ? this : new Settings(mode, limit, List.copyOf(parens)); } } }