package org.esa.snap.productlibrary.rcp.toolviews.model;
import org.esa.snap.core.datamodel.ProductData;
import org.esa.snap.engine_utilities.db.ProductEntry;
import org.esa.snap.productlibrary.rcp.toolviews.DatabasePane;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
/**
* Calculates statistic on a product entry list
*/
public class DatabaseStatistics implements DatabasePane.DatabaseQueryListener {
private final DatabasePane dbPane;
private final Map<Integer, YearData> yearDataMap = new HashMap<>(30);
private Integer overallMaxYearCnt = 0;
private Integer overallMaxDayCnt = 0;
private MonthData monthData;
private static final Calendar calendar = createCalendar();
public DatabaseStatistics(final DatabasePane dbPane) {
this.dbPane = dbPane;
dbPane.addListener(this);
}
public void notifyNewEntryListAvailable() {
updateStats(dbPane.getProductEntryList());
}
private void updateStats(final ProductEntry[] entryList) {
if(entryList == null)
return;
yearDataMap.clear();
monthData = new MonthData();
for (ProductEntry entry : entryList) {
final ProductData.UTC utc = entry.getFirstLineTime();
final Calendar cal = getAsCalendar(utc);
final int year = cal.get(Calendar.YEAR);
YearData yData = yearDataMap.get(year);
if (yData == null) {
yData = new YearData(year);
yearDataMap.put(year, yData);
}
final int dayOfYear = cal.get(Calendar.DAY_OF_YEAR);
yData.addDayOfYear(dayOfYear);
final int month = cal.get(Calendar.MONTH);
monthData.add(month);
}
// find highest year count
overallMaxYearCnt = 0;
overallMaxDayCnt = 0;
for(Integer year : yearDataMap.keySet()) {
final YearData yData = yearDataMap.get(year);
int cnt = yData.yearCnt;
int dayCnt = yData.maxDayCnt;
if(cnt > overallMaxYearCnt) {
overallMaxYearCnt = cnt;
}
if(dayCnt > overallMaxDayCnt) {
overallMaxDayCnt = dayCnt;
}
}
//showStats();
}
private static Calendar createCalendar() {
final Calendar calendar = GregorianCalendar.getInstance(ProductData.UTC.UTC_TIME_ZONE, Locale.ENGLISH);
calendar.clear();
calendar.set(2000, 0, 1);
return calendar;
}
private static Calendar getAsCalendar(final ProductData.UTC utc) {
calendar.clear();
calendar.set(2000, 0, 1);
calendar.add(Calendar.DATE, utc.getDaysFraction());
calendar.add(Calendar.SECOND, (int) utc.getSecondsFraction());
calendar.add(Calendar.MILLISECOND, (int) Math.round(utc.getMicroSecondsFraction() / 1000.0));
return calendar;
}
public Map<Integer, YearData> getYearDataMap() {
return yearDataMap;
}
public MonthData getMonthData() {
return monthData;
}
public int getOverallMaxYearCnt() {
return overallMaxYearCnt;
}
public int getOverallMaxDayCnt() {
return overallMaxDayCnt;
}
private void showStats() {
final SortedSet<Integer> years = new TreeSet<>(yearDataMap.keySet());
System.out.print("Year: ");
for (Integer y : years) {
System.out.print(y + "= " + yearDataMap.get(y).yearCnt + " ");
}
System.out.println();
final Set<Integer> months = monthData.getMonthSet();
System.out.print("Month: ");
for (Integer m : months) {
System.out.print(m + "= " + monthData.get(m) + " ");
}
System.out.println();
for (Integer y : years) {
final Map<Integer, Integer> dayOfYear = yearDataMap.get(y).dayOfYearMap;
final Set<Integer> days = dayOfYear.keySet();
System.out.print(y+ ": ");
for(Integer d : days) {
Integer dayCnt = dayOfYear.get(d);
if(dayCnt != 0) {
System.out.print(d + "=" + dayCnt + " ");
}
}
System.out.println();
}
}
public static class YearData {
public final int year;
public int yearCnt = 0;
public int maxDayCnt = 0;
public final Map<Integer, Integer> dayOfYearMap = new HashMap<>(365); // starts from 1
private boolean isSelected = true;
YearData(final int year) {
this.year = year;
// init dayOfYear
for (int d = 1; d < 366; ++d) {
dayOfYearMap.put(d, 0);
}
}
void addDayOfYear(final int dayOfYear) {
Integer dayOfYearCnt = dayOfYearMap.get(dayOfYear);
if (dayOfYearCnt == null) {
dayOfYearCnt = 1;
} else {
dayOfYearCnt += 1;
}
dayOfYearMap.put(dayOfYear, dayOfYearCnt);
// save max day cnt per year
if(dayOfYearCnt > maxDayCnt) {
maxDayCnt = dayOfYearCnt;
}
yearCnt += 1;
}
public boolean isSelected() {
return isSelected;
}
public void setSelected(final boolean selected) {
isSelected = selected;
}
}
public class MonthData {
private int maxMonthCnt = 0;
private final Map<Integer, Integer> monthMap = new HashMap<>(12); // starts from 0
MonthData() {
//init months to 0
for (int m = 0; m < 12; ++m) {
monthMap.put(m, 0);
}
}
public void add(final Integer month) {
Integer monthCnt = monthMap.get(month);
if(monthCnt != null) {
monthCnt += 1;
if(monthCnt > maxMonthCnt ) {
maxMonthCnt = monthCnt;
}
monthMap.put(month, monthCnt);
}
}
public Set<Integer> getMonthSet() {
return monthMap.keySet();
}
public Integer get(final Integer m) {
return monthMap.get(m);
}
public int getMaxMonthCnt() {
return maxMonthCnt;
}
public void setSelected(final int m, final boolean selected) {
dbPane.getDBQuery().setMonthSelected(m, selected);
dbPane.queryDatabase();
}
public boolean isSelected(final int m) {
return dbPane.getDBQuery().isMonthSelected(m);
}
}
}