001/*
002 * Copyright (c) 2015-2020, Oracle and/or its affiliates. All rights reserved.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.tribuo.util;
018
019import com.oracle.labs.mlrg.olcut.util.Pair;
020import org.tribuo.Model;
021
022import java.io.PrintStream;
023import java.util.ArrayList;
024import java.util.HashMap;
025import java.util.List;
026import java.util.Map;
027
028/**
029 * Utilities for nice HTML output that can be put in wikis and such.
030 */
031public final class HTMLOutput {
032
033    private HTMLOutput() { }
034
035    public static String toHTML(Pair<String, Double> p) {
036        String cleanName = p.getA().replace("&", "&amp;")
037                .replace("<", "&lt;")
038                .replace(">", "&gt;");
039
040        return String.format("<td style=\"text-align:left\">%s</td><td style=\"text-align:right\">%.3f</td>",
041                cleanName, p.getB());
042    }
043
044    public static void printFeatureMap(Map<String, List<Pair<String, Double>>> m, List<String> keys, PrintStream s) {
045        List<String> realKeys = new ArrayList<>(keys);
046        realKeys.add(Model.ALL_OUTPUTS);
047        if (m == null) {
048            return;
049        }
050        s.println("<table>\n<tr>");
051        for (String k : realKeys) {
052            if (m.containsKey(k)) {
053                s.printf("<th colspan=\"2\">%s</th>", k);
054            }
055        }
056        s.print("</tr>\n<tr>");
057        for (String k : realKeys) {
058            if (m.containsKey(k)) {
059                s.print("<th>Feature</th><th>Weight</th>");
060            }
061        }
062        s.println("</tr>");
063        //
064        // We'll go until all classes are out of features.
065        Map<String, Integer> pos = new HashMap<>();
066        int done = 0;
067        while (done < m.size()) {
068            s.print("<tr>");
069            for (String k : realKeys) {
070                List<Pair<String, Double>> l = m.get(k);
071                if (l == null) {
072                    continue;
073                }
074                Integer p = pos.getOrDefault(k, 0);
075                if (p >= l.size()) {
076                    //
077                    // We might be out of features for this class, so print an 
078                    // empty one.
079                    s.print("<td></td><td></td>");
080                    continue;
081                }
082                s.print(toHTML(l.get(p)));
083                p++;
084                if (p >= l.size()) {
085                    done++;
086                }
087                pos.put(k, p);
088            }
089            s.println("</tr>");
090        }
091        s.println("</table>");
092    }
093
094}