package polly.rx.core.orion.datasource;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import polly.rx.core.orion.ResourcePriceProvider;
import polly.rx.core.orion.model.DefaultProduction;
import polly.rx.core.orion.model.Production;
import polly.rx.entities.RxRessource;
import de.skuzzle.polly.sdk.time.Milliseconds;
import de.skuzzle.polly.sdk.time.Time;
import de.skuzzle.polly.tools.io.WebUtils;
public class QZoneResourcePriceProvider implements ResourcePriceProvider {
private final int QZONE_TIMEOUT = (int) Milliseconds.fromSeconds(2);
// TEST
public static void main(String[] args) {
System.out.println(new QZoneResourcePriceProvider().getAllPrices());
}
private static Map<RxRessource, Double> zeroMap() {
final Map<RxRessource, Double> result = new EnumMap<>(RxRessource.class);
for (final RxRessource ress : RxRessource.values()) {
result.put(ress, 0.);
}
result.put(RxRessource.CR, 1.);
return result;
}
private final static String API_URL = "http://qzone.spdns.de/pollyPriceDaily.php"; //$NON-NLS-1$
private Date refreshTime;
public QZoneResourcePriceProvider() {
this.refreshTime = Time.currentTime();
}
@Override
public Date getRefreshTime() {
return this.refreshTime;
}
@Override
public double getPrice(RxRessource resource) {
return this.getPrice(resource, null);
}
@Override
public double getPrice(RxRessource resource, Date time) {
return this.safeRequestPrices(time).get(resource);
}
@Override
public List<? extends Production> getAllPrices() {
return this.getAllPrices(null);
}
@Override
public List<? extends Production> getAllPrices(Date time) {
final Map<RxRessource, Double> prices = this.safeRequestPrices(time);
final List<DefaultProduction> result = new ArrayList<>(prices.size());
for (final Entry<RxRessource, Double> e : prices.entrySet()) {
result.add(new DefaultProduction(e.getKey(), e.getValue()));
}
return result;
}
private String formatDate(Date date) {
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); //$NON-NLS-1$
return df.format(date);
}
private Map<RxRessource, Double> safeRequestPrices(Date date) {
try {
return this.requestPrices(date);
} catch (IOException e) {
e.printStackTrace();
return zeroMap();
}
}
private Date parseTimeStamp(String stamp) {
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //$NON-NLS-1$
try {
return df.parse(stamp);
} catch (ParseException e) {
return Time.currentTime();
}
}
private Map<RxRessource, Double> requestPrices(Date date) throws IOException {
final String requestUrl;
final Map<RxRessource, Double> result = zeroMap();
if (date != null) {
requestUrl = API_URL + "?date=" + this.formatDate(date); //$NON-NLS-1$
} else {
requestUrl = API_URL;
}
final StringBuilder response = WebUtils.getString(requestUrl, QZONE_TIMEOUT);
int i = 0;
final String rows[] = response.toString().split(System.lineSeparator());
for (final String row : rows) {
if (!this.interpretResponseLine(row, i++, result, date != null)) {
return result;
}
}
return result;
}
private boolean interpretResponseLine(String line, int lineNr,
Map<RxRessource, Double> result, boolean dateGiven) {
final String[] parts = line.split(";"); //$NON-NLS-1$
if (lineNr == 0) {
final int id = Integer.parseInt(parts[1]);
if (id == 0) {
return false;
}
} else if (lineNr == 3 && !dateGiven) {
this.refreshTime = parseTimeStamp(parts[1]);
} else if (lineNr > 4 && !dateGiven) {
//
final int ordinal = lineNr - 4;
final double price = Math.round(Double.parseDouble(parts[1]) * 100.0) / 100.0;
result.put(RxRessource.values()[ordinal], price);
} else if (lineNr > 1 && dateGiven) {
// -2 would be Cr, so we start at nrg with -1
final int ordinal = lineNr - 1;
final double price = Math.round(Float.parseFloat(parts[1]) * 100.0) / 100.0;
result.put(RxRessource.values()[ordinal], price);
}
return true;
}
}