/*
* Copyright (C) 2015-2017 たんらる
*/
package fourthline.mmlTools.core;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public final class MMLTickTable {
private static final int COMBN = 2;
public static final int TPQN = 96;
/**
* For MML text -> tick
*/
private final LinkedHashMap<String, Integer> tickTable = new LinkedHashMap<>();
/**
* For tick -> MML text
*/
private final LinkedHashMap<Integer, List<String>> tickInvTable = new LinkedHashMap<>();
public static MMLTickTable createTickTable() {
MMLTickTable tickTable = new MMLTickTable();
return tickTable;
}
MMLTickTable() {
NanoTime time = NanoTime.start();
generateTickTable();
generateInvTable();
System.out.println("MMLTickTable " + time.ms() + "ms");
}
MMLTickTable(InputStream inputStream) {
long startTime = System.currentTimeMillis();
generateTickTable();
readFromInputStreamInvTable(inputStream);
long endTime = System.currentTimeMillis();
System.out.println("MMLTickTable " + (endTime - startTime) + "ms");
}
public Map<Integer, List<String>> getInvTable() {
return this.tickInvTable;
}
public Map<String, Integer> getTable() {
return this.tickTable;
}
private void add(int l, boolean dot) {
int tick = (int)( TPQN*4 / l );
if (dot) {
tick += tick / 2;
}
String s = l+(dot?".":"");
tickTable.put(s, tick);
}
private void generateTickTable() {
for (int i = 1; i <= 64; i++) {
add(i, true);
add(i, false);
}
}
private int patternLength(List<String> pattern) {
int len = 0;
List<String> spll = Arrays.asList("1", "2", "4", "8", "16");
for (String s : pattern) {
if (spll.stream().anyMatch(s::equals)) {
len += s.length();
} else if (spll.stream().map(t -> t+".").anyMatch(s::equals)) {
len += s.length()*2;
} else {
len += s.length()*3;
}
}
return len + pattern.size()*10;
}
private void generateInvTable() {
String keys[] = tickTable.keySet().toArray(new String[tickTable.size()]);
int mTick = tickTable.values().stream().max(Integer::compare).get();
for (int i = 1; i <= COMBN; i++) {
List<List<String>> pattern = new Combination<>(keys, i).getArray();
for (List<String> list : pattern) {
int tick = list.stream().mapToInt(tickTable::get).sum();
if (tick > mTick) {
continue;
}
if (!tickInvTable.containsKey(tick)) {
tickInvTable.put(tick, list);
} else {
List<String> currentList = tickInvTable.get(tick);
if ( (patternLength(list) <= patternLength(currentList)) ) {
tickInvTable.put(tick, list);
}
}
}
}
}
void writeToOutputStreamInvTable(OutputStream outputStream) {
try {
PrintStream stream = new PrintStream(outputStream, false, "UTF-8");
stream.println("# Generated Text --- ");
stream.println("# registered key: " + tickInvTable.size());
int max = tickInvTable.keySet().stream().max(Integer::compare).get();
for (int i = 1; i <= max; i++) {
if (tickInvTable.containsKey(i)) {
stream.print(i+"=");
tickInvTable.get(i).forEach( s -> {
stream.print("[" + s + "]");
});
stream.println();
} else {
stream.println("# "+i+"=<< not supported >>");
}
}
} catch (UnsupportedEncodingException e) {}
}
private void readFromInputStreamInvTable(InputStream inputStream) {
try {
InputStreamReader reader = new InputStreamReader(inputStream, "UTF-8");
new BufferedReader(reader).lines().forEach(s -> {
if (!s.startsWith("#")) {
int keySep = s.indexOf('=');
String key = s.substring(0, keySep);
String itemList = s.substring(keySep+1);
ArrayList<String> valueList = new ArrayList<>();
while (itemList.length() > 0) {
int itemIndex = itemList.indexOf(']');
String item = itemList.substring(1, itemIndex);
valueList.add(item);
itemList = itemList.substring(itemIndex+1);
}
tickInvTable.put(Integer.parseInt(key), valueList);
}
});
} catch (UnsupportedEncodingException e) {}
}
private void printTickList() {
writeToOutputStreamInvTable(System.out);
}
public static void main(String args[]) {
MMLTickTable tickTable = new MMLTickTable();
tickTable.printTickList();
}
}