blob: 0b3aacd70efff45601af7907111f327339030187 [file] [log] [blame]
package org.unicode.cldr.util;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Pattern;
import org.unicode.cldr.draft.FileUtilities;
import org.unicode.cldr.test.BuildIcuCompactDecimalFormat;
import org.unicode.cldr.test.BuildIcuCompactDecimalFormat.CurrencyStyle;
import org.unicode.cldr.tool.Option;
import org.unicode.cldr.tool.Option.Options;
import org.unicode.cldr.tool.ShowData;
import org.unicode.cldr.tool.ShowPlurals;
import org.unicode.cldr.tool.TablePrinter;
import org.unicode.cldr.util.CLDRFile.DraftStatus;
import org.unicode.cldr.util.PathHeader.PageId;
import org.unicode.cldr.util.SupplementalDataInfo.PluralInfo;
import com.ibm.icu.text.CompactDecimalFormat;
import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
import com.ibm.icu.text.NumberFormat;
import com.ibm.icu.util.Currency;
import com.ibm.icu.util.ICUUncheckedIOException;
import com.ibm.icu.util.ULocale;
public class VerifyCompactNumbers {
private static final CLDRConfig CLDR_CONFIG = CLDRConfig.getInstance();
private static final String DIR = CLDRPaths.CHART_DIRECTORY + "verify/numbers/";
final static Options myOptions = new Options();
enum MyOptions {
organization(".*", "CLDR", "organization"), filter(".*", ".*", "locale filter (regex)"), currency(".*", "EUR", "show currency"),;
// boilerplate
final Option option;
MyOptions(String argumentPattern, String defaultArgument, String helpText) {
option = myOptions.add(this, argumentPattern, defaultArgument, helpText);
}
}
// later, look at DateTimeFormats to set up as an HTML table
private static final Set<String> USES_GROUPS_OF_4 = new HashSet<String>(Arrays.asList("ko", "ja", "zh", "zh_Hant"));
/**
* Produce a set of static tables from the vxml data. Only a stopgap until the above is integrated into ST.
*
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
myOptions.parse(MyOptions.organization, args, true);
FileCopier.copy(ShowData.class, "verify-index.html", DIR, "index.html");
FileCopier.copy(ShowData.class, "index.css", DIR, "index.css");
String organization = MyOptions.organization.option.getValue();
String filter = MyOptions.filter.option.getValue();
boolean showCurrency = true; // MyOptions.currency.option.doesOccur();
String currencyCode = MyOptions.currency.option.getValue();
Factory factory2 = Factory.make(CLDRPaths.MAIN_DIRECTORY, filter);
CLDRFile englishCldrFile = factory2.make("en", true);
SupplementalDataInfo sdi = CLDR_CONFIG.getSupplementalDataInfo();
Set<String> defaultContentLocales = sdi.getDefaultContentLocales();
NumberFormat enf = NumberFormat.getIntegerInstance(ULocale.ENGLISH);
enf.setGroupingUsed(false);
Set<String> availableLanguages = new TreeSet<String>(factory2.getAvailableLanguages());
if (Pattern.matches(filter, "pt_PT")) {
availableLanguages.add("pt_PT");
}
PrintWriter plainText = FileUtilities.openUTF8Writer(DIR, "compactTestFile.txt");
DateTimeFormats.writeCss(DIR);
final CLDRFile english = CLDR_CONFIG.getEnglish();
Map<String, String> indexMap = new TreeMap<>(CLDR_CONFIG.getCollator());
for (String locale : availableLanguages) {
if (defaultContentLocales.contains(locale)) {
continue;
}
Level level = StandardCodes.make().getLocaleCoverageLevel(organization, locale);
if (Level.MODERN.compareTo(level) > 0) {
continue;
}
// TODO: fix to ignore locales with no data.
if (locale.equals("ne") || locale.equals("cy")) {
continue;
}
PrintWriter out = FileUtilities.openUTF8Writer(DIR, locale + ".html");
String title = "Verify Number Formats: " + englishCldrFile.getName(locale);
out.println("<!doctype HTML PUBLIC '-//W3C//DTD HTML 4.0 Transitional//EN'><html><head>\n" +
"<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>\n" +
"<title>" + title + "</title>\n" +
"<link rel='stylesheet' type='text/css' href='index.css'>\n" +
"</head><body><h1>" + title + "</h1>\n"
+ "<p><a href='index.html'>Index</a></p>\n");
CLDRFile cldrFile = factory2.make(locale, true, DraftStatus.contributed);
showNumbers(cldrFile, showCurrency, currencyCode, out, factory2);
out.println("</body></html>");
out.close();
indexMap.put(english.getName(locale), locale + ".html");
}
try (PrintWriter index = DateTimeFormats.openIndex(DIR, "Numbers")) {
DateTimeFormats.writeIndexMap(indexMap, index);
}
plainText.close();
}
public static void showNumbers(CLDRFile cldrFile, boolean showCurrency,
String currencyCode, Appendable out, Factory factory) {
try {
Set<String> debugCreationErrors = new LinkedHashSet<String>();
Set<String> errors = new LinkedHashSet<String>();
String locale = cldrFile.getLocaleID();
TablePrinter tablePrinter1 = new TablePrinter()
// .setCaption("Timezone Formats")
.setTableAttributes("class='dtf-table'")
.addColumn("Numeric Format").setHeaderCell(true).setHeaderAttributes("class='dtf-th'")
.setCellAttributes("class='dtf-s'")
.addColumn("Compact-Short").setHeaderAttributes("class='dtf-th'").setCellAttributes("class='dtf-s'")
.addColumn("Compact-Long").setHeaderAttributes("class='dtf-th'").setCellAttributes("class='dtf-s'");
if (showCurrency) {
tablePrinter1
.addColumn("Compact-Short<br>+Currency")
.setHeaderAttributes("class='dtf-th'")
.setCellAttributes("class='dtf-s'")
// .addColumn("Compact-Short<br>+Unit")
// .setHeaderAttributes("class='dtf-th'")
// .setCellAttributes("class='dtf-s'")
// .addColumn("Compact-Long<br>+Currency")
// .addColumn("Compact-Long<br>+Currency-Long")
// .addColumn("Numeric Format").setHeaderCell(true).setHeaderAttributes("class='dtf-th'")
// .setCellAttributes("class='dtf-s'")
;
}
// tablePrinter1.addColumn("View").setHeaderCell(true).setHeaderAttributes("class='dtf-th'").setCellAttributes("class='dtf-s'");
;
ULocale locale2 = new ULocale(locale);
NumberFormat nf = NumberFormat.getInstance(locale2);
// nf.setMaximumFractionDigits(0);
SupplementalDataInfo sdi = CLDR_CONFIG.getSupplementalDataInfo();
PluralInfo pluralInfo = sdi.getPlurals(locale);
String[] debugOriginals = null;
CompactDecimalFormat cdf = BuildIcuCompactDecimalFormat.build(cldrFile, debugCreationErrors,
debugOriginals, CompactStyle.SHORT, locale2, CurrencyStyle.PLAIN, currencyCode);
captureErrors(debugCreationErrors, errors, locale, "short");
CompactDecimalFormat cdfs = BuildIcuCompactDecimalFormat.build(cldrFile, debugCreationErrors,
debugOriginals, CompactStyle.LONG, locale2, CurrencyStyle.PLAIN, currencyCode);
captureErrors(debugCreationErrors, errors, locale, "long");
CompactDecimalFormat cdfCurr = BuildIcuCompactDecimalFormat.build(cldrFile, debugCreationErrors,
debugOriginals, CompactStyle.SHORT, locale2, CurrencyStyle.CURRENCY, currencyCode);
captureErrors(debugCreationErrors, errors, locale, "short-curr");
// CompactDecimalFormat cdfU = BuildIcuCompactDecimalFormat.build(cldrFile, debugCreationErrors,
// debugOriginals, CompactStyle.SHORT, locale2, CurrencyStyle.UNIT, "EUR");
// captureErrors(debugCreationErrors, errors, locale, "short-kg");
// CompactDecimalFormat cdfsCurr = BuildIcuCompactDecimalFormat.build(cldrFile, debugCreationErrors,
// debugOriginals, CompactStyle.SHORT, locale2, CurrencyStyle.CURRENCY, currencyCode);
// CompactDecimalFormat cdfsCurrISO = BuildIcuCompactDecimalFormat.build(cldrFile, debugCreationErrors,
// debugOriginals, CompactStyle.LONG, locale2, CurrencyStyle.ISO_CURRENCY, "EUR");
// Collect samples for display
// one path for group-3, one for group-4
// TODO, fix for indic.
int factor = USES_GROUPS_OF_4.contains(locale) ? 10000 : 1000;
// we want to collect a sample of at least one sample for each plural category for each
// power of ten
Set<Double> samples = new TreeSet<Double>();
samples.add(1.1d);
samples.add(1.5d);
samples.add(1100d);
collectItems(pluralInfo, 1, 10, samples);
collectItems(pluralInfo, 10, 100, samples);
collectItems(pluralInfo, 100, 1000, samples);
int sigDigits = 3;
if (factor > 1000) {
collectItems(pluralInfo, 1000, 10000, samples);
sigDigits = 4;
}
if (cdf != null) {
cdf.setMaximumSignificantDigits(sigDigits);
}
if (cdfs != null) {
cdfs.setMaximumSignificantDigits(sigDigits);
}
if (cdfCurr != null) {
cdfCurr.setCurrency(Currency.getInstance(currencyCode));
cdfCurr.setMaximumSignificantDigits(sigDigits);
}
// cdfU.setMaximumSignificantDigits(sigDigits);
// for (Entry<Count, List<Double>> entry : pluralInfo.getCountToExamplesMap().entrySet()) {
// samples.add(entry.getValue().get(0));
// }
//
// Set<Double> samples2 = new TreeSet<Double>();
// for (int i = 10; i < factor; i *= 10) {
// for (Double sample : samples) {
// samples2.add(sample*i);
// }
// }
// samples.addAll(samples2);
Set<Double> allSamples = new TreeSet<Double>();
for (long i = 1; i <= 100000000000000L; i *= factor) {
for (Double sample : samples) {
double source = i * sample;
allSamples.add(source);
}
}
try {
for (double source : allSamples) {
if (false && source == 22000000 && locale.equals("cs")) {
System.out.println("**");
}
String formattedNumber = nf.format(source);
String compactFormattedNumber = cdf == null ? "n/a" : cdf.format(source);
String compactLongFormattedNumber = cdfs == null ? "n/a" : cdfs.format(source);
// plainText.println(locale
// + "\t__" + source
// + "\t__" + compactFormattedNumber
// + "\t__" + compactLongFormattedNumber
// );
tablePrinter1.addRow()
.addCell(formattedNumber)
.addCell(compactFormattedNumber)
.addCell(compactLongFormattedNumber);
if (showCurrency) {
tablePrinter1
.addCell(cdfCurr == null ? "n/a" : cdfCurr.format(source))
// .addCell(cdfU.format(source))
// .addCell(cdfsCurr.format(source))
// .addCell(cdfsCurrLong.format(source))
// .addCell(cdfsCurrLong.format(source))
//.addCell(formattedNumber)
;
}
// String view = PathHeader.getLinkedView(surveyUrl, cldrFile, METAZONE_PREFIX + metazone + METAZONE_SUFFIX);
// tablePrinter1.addCell(view == null
// ? ""
// : view);
tablePrinter1
.finishRow();
}
} catch (Exception e) {
e.printStackTrace();
}
out.append("<p>To correct problems in compact numbers below, please go to "
+ PathHeader.SECTION_LINK
+ CLDR_CONFIG.urls().forPage(cldrFile.getLocaleID(), PageId.Compact_Decimal_Formatting)
+ "'><em>" + PageId.Compact_Decimal_Formatting
+ "</em></a>.</p>");
out.append(tablePrinter1.toString() + "\n");
out.append("<h3>Plural Rules</h3>");
out.append("<p>Look over the Minimal Pairs to make sure they are ok. "
+ "Then review the examples in the cell to the left. "
+ "All of those you should be able to substitute for the numbers in the Minimal Pairs, "
+ "with an acceptable result. "
+ "If any would be incorrect, please "
+ "<a target='ticket' href='https://unicode.org/cldr/trac/newticket'>file a ticket</a>.</p>"
+ "<p>For more details, see " +
"<a target='CLDR-ST-DOCS' href='http://cldr.unicode.org/index/cldr-spec/plural-rules'>Plural Rules</a>.</p>");
ShowPlurals showPlurals = new ShowPlurals(CLDR_CONFIG.getSupplementalDataInfo());
showPlurals.printPluralTable(cldrFile, locale, out, factory);
showPlurals.appendBlanksForScrolling(out);
showErrors(errors, out);
showErrors(debugCreationErrors, out);
} catch (IOException e) {
throw new ICUUncheckedIOException(e);
}
}
private static String surveyUrl = CLDR_CONFIG.getProperty("CLDR_SURVEY_URL",
"http://st.unicode.org/cldr-apps/survey");
private static void showErrors(Set<String> errors, Appendable out) throws IOException {
if (errors.size() != 0) {
out.append("<h2>" + "Errors" + "</h2>\n");
for (String s : errors) {
out.append("<p>" + s + "</p>\n");
}
errors.clear();
}
}
private static Set<Double> collectItems(PluralInfo pluralInfo, double start, double limit,
Set<Double> samples) {
// TODO optimize once we have all the keywords
Map<String, Double> ones = new TreeMap<String, Double>();
for (double i = start; i < limit; ++i) {
String cat = pluralInfo.getPluralRules().select(i);
if (ones.containsKey(cat)) {
continue;
}
ones.put(cat, i);
}
samples.addAll(ones.values());
return samples;
}
private static void captureErrors(Set<String> debugCreationErrors, Set<String> errors, String locale, String length) {
if (debugCreationErrors.size() != 0) {
for (String s : debugCreationErrors) {
errors.add(locale + "\t" + length + "\t" + s);
}
debugCreationErrors.clear();
}
}
}