/** * CrowdTransEval, a toolkit for evaluating machine translation system by using * crowdsourcing. Copyright (C) 2012 Alejandro Navarro Fulleda <anf5@alu.ua.es> * * This program 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. * * This program 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 * this program. If not, see <http://www.gnu.org/licenses/>. */ package es.ua.alex952.cf_helpers.result_helpers; import es.ua.alex952.cf_helpers.params.JSONParams; import es.ua.alex952.cf_helpers.translation_services.Service; import java.awt.Desktop; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** * <<Singleton>> * * @author alex952 */ public class HTMLGenerator { private String headTop = ""; private String head = ""; private String headBottom = ""; private String bodyTop = ""; private String body = ""; private String bodyBottom = ""; private String htmlGenerated = ""; private static HTMLGenerator instance = null; /** * Private constructor */ private HTMLGenerator() { } /** * Entrance point of the class (Singleton pattern). * * @return Unique instance of the class */ public static HTMLGenerator getGenerator() { if (instance == null) { instance = new HTMLGenerator(); } return instance; } /** * Utility function that generates the CML associated to the Job to put it * into the creation parameters. * * @return The CML generated. */ public static String generateCML(Service[] services) { String cml = "<p><strong>Original sentence: </strong>{{lo}}</p>" + "<p><strong>Reference translation: </strong>{{tr}}</p>"; cml += "<table>"; for (Service c : services) { cml += "<tr>"; cml += "<td>{{" + c.getName() + "}}</td>" + "<td>" + "<cml:ratings validates=\"required\" label=\"Adequacy\" name=\"adequacy_" + c.getName() + "\" gold=\"true\">" + "<cml:rating label=\"0\" value=\"0\" />" + "<cml:rating label=\"1\" value=\"1\" />" + "<cml:rating label=\"2\" value=\"2\" />" + "<cml:rating label=\"3\" value=\"3\" />" + "<cml:rating label=\"4\" value=\"4\" />" + "<cml:rating label=\"5\" value=\"5\" />" + "</cml:ratings>" + "</td>" + "<td>" + "<cml:ratings validates=\"required\" label=\"Fluency\" name=\"fluency_" + c.getName() + "\" gold=\"true\">" + "<cml:rating label=\"0\" value=\"0\" />" + "<cml:rating label=\"1\" value=\"1\" />" + "<cml:rating label=\"2\" value=\"2\" />" + "<cml:rating label=\"3\" value=\"3\" />" + "<cml:rating label=\"4\" value=\"4\" />" + "<cml:rating label=\"5\" value=\"5\" />" + "</cml:ratings>" + "</td>"; cml += "</tr>"; } cml += "</table>"; return cml; } /** * Generates charts representing the Kappa average for each service (fluency * and adequacy). * * @param raters Hashmap of pairs of raters */ public void generateKappaAverageCharts(HashMap<String, HashMap<String, KappaRaters>> raters) { String chart = "var adequacy = new google.visualization.DataTable();\n" + "adequacy.addColumn(\"string\", \"Service\");\n" + "adequacy.addColumn(\"number\", \"Adequacy\");\n" + "var fluency = new google.visualization.DataTable();\n" + "fluency.addColumn(\"string\", \"Service\");\n" + "fluency.addColumn(\"number\", \"Fluency\");\n"; String adata = ""; String fdata = ""; Set<String> services = (Set<String>) raters.keySet(); int scount = 0; for (String service : services) { HashMap<String, KappaRaters> serviceRatters = raters.get(service); double f = 0.0; double a = 0.0; for (String key : serviceRatters.keySet()) { f += serviceRatters.get(key).getFluencyKappa(); a += serviceRatters.get(key).getAdequacyKappa(); } f /= serviceRatters.size(); a /= serviceRatters.size(); adata += "['" + service + "', " + a + "]"; fdata += "['" + service + "', " + f + "]"; if (scount++ < services.size() - 1) { adata += ","; fdata += ","; } } chart += "adequacy.addRows([\n" + adata + "]);\n"; chart += "fluency.addRows([\n" + fdata + "]);\n"; chart += "var optionsA = {\n" + "title: 'Translation\\'s Adequacy by translation service',\n" + "hAxis: {title: 'Adequacy', titleTextStyle: {color: 'red'}}};\n"; chart += "var optionsF = {\n" + "title: 'Translation\\'s Fluency by translation service',\n" + "hAxis: {title: 'Fluency', titleTextStyle: {color: 'red'}}};\n"; chart += "var chartA = new google.visualization.ColumnChart(document.getElementById('kappa_average_adequacy'));\n"; chart += "var chartF = new google.visualization.ColumnChart(document.getElementById('kappa_average_fluency'));\n"; chart += "chartA.draw(adequacy, optionsA);\n"; chart += "chartF.draw(fluency, optionsF);\n"; head += chart; body += "<h2>Kappa averages by service</h2>\n" + "<div id='kappa_average_adequacy'></div>\n" + "<div id='kappa_average_fluency'></div>\n"; } public void generateScoreCharts(JSONParams judgments, Service[] services) { String chart = "var adequacy = new google.visualization.DataTable();\n" + "adequacy.addColumn(\"string\", \"Service\");\n" + "adequacy.addColumn(\"number\", \"Adequacy\");\n" + "var fluency = new google.visualization.DataTable();\n" + "fluency.addColumn(\"string\", \"Service\");\n" + "fluency.addColumn(\"number\", \"Fluency\");\n"; String adata = ""; String fdata = ""; Double[] acumFluencyServices = new Double[services.length]; Double[] acumAdequacyServices = new Double[services.length]; Iterator<String> unitsIterator = judgments.getKeySet(); while (unitsIterator.hasNext()) { String u = unitsIterator.next(); JSONParams unit = judgments.getObject(u); for (int i = 0; i < services.length; i++) { String service = services[i].getName(); acumFluencyServices[i] = Double.parseDouble(unit.getObject("fluency_" + service).getProperty("avg")); acumAdequacyServices[i] = Double.parseDouble(unit.getObject("adequacy_" + service).getProperty("avg")); } } for (int i = 0; i < services.length; i++) { acumFluencyServices[i] /= judgments.size(); acumAdequacyServices[i] /= judgments.size(); } for (int i = 0; i < services.length; i++) { String service = services[i].getName(); adata += "['" + service + "', " + acumAdequacyServices[i] + "]"; fdata += "['" + service + "', " + acumFluencyServices[i] + "]"; if (i < services.length - 1) { adata += ","; fdata += ","; } } chart += "adequacy.addRows([\n" + adata + "]);\n"; chart += "fluency.addRows([\n" + fdata + "]);\n"; chart += "var optionsA = {\n" + "title: 'Translation\\'s Adequacy by translation service',\n" + "hAxis: {title: 'Adequacy', titleTextStyle: {color: 'red'}}};\n"; chart += "var optionsF = {\n" + "title: 'Translation\\'s Fluency by translation service',\n" + "hAxis: {title: 'Fluency', titleTextStyle: {color: 'red'}}};\n"; chart += "var chartA = new google.visualization.ColumnChart(document.getElementById('score_average_adequacy'));\n"; chart += "var chartF = new google.visualization.ColumnChart(document.getElementById('score_average_fluency'));\n"; chart += "chartA.draw(adequacy, optionsA);\n"; chart += "chartF.draw(fluency, optionsF);\n"; head += chart; body += "<h2>Adequacy/Fluency averages by service</h2>\n" + "<div id='score_average_adequacy'></div>\n" + "<div id='score_average_fluency'></div>\n"; } /** * Generates a table for each service containing the info about factor Kappa * calculated every pair of raters. * * @param raters Hashmap of pairs of raters */ public void generateKappaTable(HashMap<String, HashMap<String, KappaRaters>> raters) { for (String service : raters.keySet()) { HashMap<String, KappaRaters> serviceRatters = raters.get(service); body += "<h2>Kappa results for service " + service + "</h2>\n" + "<h3>Fluency kappa</h3>\n" + "<div id=\"kappa_fluency_" + service + "\"></div>\n" + "<h3>Adequacy kappa</h3>\n" + "<div id=\"kappa_adequacy_" + service + "\"></div>\n"; HashSet<Integer> leftPart = new HashSet<Integer>(); HashSet<Integer> rightPart = new HashSet<Integer>(); for (String key : serviceRatters.keySet()) { KappaRaters rater = serviceRatters.get(key); leftPart.add(rater.getRaterA()); rightPart.add(rater.getRaterB()); } String dataFluency = "var dataFluency = google.visualization.arrayToDataTable([\n" + "[ ' ', "; String dataAdequacy = "var dataAdequacy = google.visualization.arrayToDataTable([\n" + "[ ' ', "; int count = 0; for (Integer right : rightPart) { dataFluency += "'" + right.toString() + "'"; dataAdequacy += "'" + right.toString() + "'"; if (count++ < rightPart.size() - 1) { dataFluency += ", "; dataAdequacy += ", "; } } dataFluency += "],\n"; dataAdequacy += "],\n"; int countl = 0; int countr = 0; for (Integer left : leftPart) { dataFluency += "[ '" + left + "', "; dataAdequacy += "[ '" + left + "', "; for (Integer right : rightPart) { if (serviceRatters.containsKey(left + "/" + right)) { KappaRaters k = serviceRatters.get(left + "/" + right); dataFluency += "'" + k.getFluencyKappa() + "'"; dataAdequacy += "'" + k.getAdequacyKappa() + "'"; } else { dataFluency += "false"; dataAdequacy += "false"; } if (countr++ < rightPart.size() - 1) { dataFluency += ", "; dataAdequacy += ", "; } } dataFluency += "]"; dataAdequacy += "]"; if (countl++ < rightPart.size() - 1) { dataFluency += ", "; dataAdequacy += ", "; } dataFluency += "\n"; dataAdequacy += "\n"; } dataFluency += "]);\n"; dataAdequacy += "]);\n"; head += dataAdequacy + dataFluency + "visualizationFluency = new google.visualization.Table(document.getElementById('kappa_fluency_" + service + "'));\n" + "visualizationAdequacy = new google.visualization.Table(document.getElementById('kappa_adequacy_" + service + "'));\n" + "visualizationFluency.draw(dataFluency, null);\n" + "visualizationAdequacy.draw(dataAdequacy, null);\n"; } } /* * public String generateHTML(HashMap<String, HashMap<String, KappaRaters>> * raters) { this.generateSurrondings(); return this.htmlGenerated; } */ /** * Returns the html generated by the above procedures along with the headers * and extra tags for a complete html output. * * @return Complete HTML file (String) with all the contente generated */ public String getHTML() { String html = ""; if (this.headTop == null || this.headTop.equals("")) { generateSurrondings(); } html = this.headTop + this.head + this.headBottom + this.bodyTop + this.body + this.bodyBottom; return html; } /** * Generate the headers and extra tags of the resultant HTML. */ private void generateSurrondings() { this.headTop = "<html>\n" + "<head>\n" + "<script type=\"text/javascript\" src=\"https://www.google.com/jsapi\"></script>\n" + "<script type=\"text/javascript\">\n" + "google.load(\"visualization\", \"1\", {packages:[\"corechart\", \"table\"]});\n" + "google.setOnLoadCallback(drawCharts);\n" + "function drawCharts() {\n"; this.headBottom = "}\n" + "</script>\n" + "</head>\n"; this.bodyTop = "<body>\n"; this.bodyBottom = "</body>\n</html>"; } /** * See {@link HTMLGenerator#getHTML()} * * @return */ public String toString() { return this.getHTML(); } public static void main(String[] args) { HTMLGenerator gen = HTMLGenerator.getGenerator(); HashMap<String, HashMap<String, KappaRaters>> rater = new HashMap<String, HashMap<String, KappaRaters>>(); rater.put("google", new HashMap<String, KappaRaters>()); rater.put("bing", new HashMap<String, KappaRaters>()); HashMap<String, KappaRaters> googleRaters = rater.get("google"); KappaRaters g12 = new KappaRaters(1, 2); KappaRaters g13 = new KappaRaters(1, 3); g12.addAdequacy(2, 1); g12.addAdequacy(3, 4); g12.addAdequacy(4, 4); g12.addAdequacy(4, 4); g12.addAdequacy(4, 1); g12.addAdequacy(4, 2); g12.addAdequacy(4, 2); g12.addAdequacy(4, 2); g12.addAdequacy(0, 2); g12.addAdequacy(0, 0); g12.addAdequacy(0, 0); g12.addAdequacy(0, 0); g12.addAdequacy(0, 0); g12.addAdequacy(0, 0); g12.addAdequacy(0, 0); g12.addAdequacy(0, 0); g12.addAdequacy(0, 0); g12.addAdequacy(0, 0); g12.addAdequacy(0, 0); g12.addAdequacy(0, 0); g12.addAdequacy(0, 0); g12.addAdequacy(0, 0); g12.addAdequacy(0, 0); g12.addAdequacy(0, 0); g12.addAdequacy(0, 4); g12.addAdequacy(0, 2); g12.addAdequacy(0, 2); g12.addAdequacy(0, 2); g12.addAdequacy(0, 2); g12.addAdequacy(4, 2); g12.addAdequacy(3, 4); g12.addAdequacy(1, 2); g12.addAdequacy(1, 2); g12.addAdequacy(1, 2); g12.addAdequacy(1, 2); g12.addAdequacy(1, 2); g12.addAdequacy(1, 2); g12.addAdequacy(2, 4); g12.addAdequacy(2, 1); g12.addAdequacy(5, 5); g12.addAdequacy(5, 5); g12.addAdequacy(5, 5); g12.addAdequacy(5, 5); g12.addAdequacy(5, 5); g12.addAdequacy(5, 5); g12.addAdequacy(3, 4); g12.addAdequacy(3, 4); g12.addFluency(2, 1); g12.addFluency(3, 4); g12.addFluency(4, 4); g12.addFluency(4, 4); g12.addFluency(4, 1); g12.addFluency(4, 2); g12.addFluency(4, 2); g12.addFluency(4, 2); g12.addFluency(0, 2); g12.addFluency(0, 0); g12.addFluency(0, 0); g12.addFluency(0, 0); g12.addFluency(0, 0); g12.addFluency(0, 0); g12.addFluency(0, 0); g12.addFluency(0, 0); g12.addFluency(0, 0); g12.addFluency(0, 0); g12.addFluency(0, 0); g12.addFluency(0, 0); g12.addFluency(0, 0); g12.addFluency(0, 0); g12.addFluency(0, 0); g12.addFluency(0, 0); g12.addFluency(0, 4); g12.addFluency(0, 2); g12.addFluency(0, 2); g12.addFluency(0, 2); g12.addFluency(0, 2); g12.addFluency(4, 2); g12.addFluency(3, 4); g12.addFluency(1, 2); g12.addFluency(1, 2); g12.addFluency(1, 2); g12.addFluency(1, 2); g12.addFluency(1, 2); g12.addFluency(1, 2); g12.addFluency(2, 4); g12.addFluency(2, 1); g12.addFluency(5, 5); g12.addFluency(5, 5); g12.addFluency(5, 5); g12.addFluency(5, 5); g12.addFluency(5, 5); g12.addFluency(5, 5); g12.addFluency(3, 4); g12.addFluency(3, 4); g13.addAdequacy(2, 1); g13.addAdequacy(3, 4); g13.addAdequacy(4, 4); g13.addAdequacy(4, 4); g13.addAdequacy(4, 1); g13.addAdequacy(4, 2); g13.addAdequacy(4, 2); g13.addAdequacy(4, 2); g13.addAdequacy(0, 2); g13.addAdequacy(0, 0); g13.addAdequacy(0, 0); g13.addAdequacy(0, 0); g13.addAdequacy(0, 0); g13.addAdequacy(0, 0); g13.addAdequacy(0, 4); g13.addAdequacy(0, 2); g13.addAdequacy(0, 2); g13.addAdequacy(0, 2); g13.addAdequacy(0, 2); g13.addAdequacy(4, 2); g13.addAdequacy(3, 4); g13.addAdequacy(1, 2); g13.addAdequacy(1, 2); g13.addAdequacy(1, 2); g13.addAdequacy(1, 2); g13.addAdequacy(1, 2); g13.addAdequacy(1, 2); g13.addAdequacy(2, 4); g13.addAdequacy(2, 1); g13.addAdequacy(5, 5); g13.addAdequacy(5, 5); g13.addAdequacy(5, 5); g13.addAdequacy(5, 5); g13.addAdequacy(5, 5); g13.addAdequacy(5, 5); g13.addAdequacy(3, 4); g13.addAdequacy(3, 4); g13.addFluency(2, 1); g13.addFluency(3, 4); g13.addFluency(4, 4); g13.addFluency(4, 4); g13.addFluency(4, 1); g13.addFluency(4, 2); g13.addFluency(4, 2); g13.addFluency(4, 2); g13.addFluency(0, 2); g13.addFluency(0, 0); g13.addFluency(0, 0); g13.addFluency(0, 0); g13.addFluency(0, 0); g13.addFluency(0, 0); g13.addFluency(0, 4); g13.addFluency(0, 2); g13.addFluency(0, 2); g13.addFluency(0, 2); g13.addFluency(0, 2); g13.addFluency(4, 2); g13.addFluency(3, 4); g13.addFluency(1, 2); g13.addFluency(1, 2); g13.addFluency(1, 2); g13.addFluency(1, 2); g13.addFluency(1, 2); g13.addFluency(1, 2); g13.addFluency(2, 4); g13.addFluency(2, 1); g13.addFluency(5, 5); g13.addFluency(5, 5); g13.addFluency(5, 5); g13.addFluency(5, 5); g13.addFluency(5, 5); g13.addFluency(5, 5); g13.addFluency(3, 4); g13.addFluency(3, 4); googleRaters.put("1/2", g12); //googleRaters.put("1/3", g13); HashMap<String, KappaRaters> bingRaters = rater.get("bing"); //bingRaters.put("1/2", g12); bingRaters.put("1/3", g13); gen.generateKappaTable(rater); gen.generateKappaAverageCharts(rater); String html = gen.getHTML(); try { FileOutputStream fos = new FileOutputStream(new File("debug.html")); fos.write(html.getBytes()); fos.close(); Desktop.getDesktop().open(new File("debug.html")); } catch (IOException e) { } } }