// Path: src/main/java/org/cri/redmetrics/model/BinCount.java
// public class BinCount {
//     public BinCount(Date date, long count) {
//         this.date = date;
//         this.count = count;
//     }
// 
//     public Date date;
//     public long count;
// }
// 
// Path: src/main/java/org/cri/redmetrics/model/GameVersion.java
// @Data
// @DatabaseTable(tableName = "game_versions")
// @NoArgsConstructor
// @AllArgsConstructor
// @EqualsAndHashCode(callSuper = true)
// public class GameVersion extends Entity {
// 
//     @DatabaseField(
//             canBeNull = false,
//             foreign = true,
//             columnDefinition = "VARCHAR, FOREIGN KEY (game_id) REFERENCES games(id)")
//     private Game game;
// 
//     @DatabaseField(canBeNull = false)
//     private String name;
// 
//     @DatabaseField
//     private String author;
// 
//     @DatabaseField
//     private String description;
// 
// }
// 
// Path: src/main/java/org/cri/redmetrics/model/Player.java
// @Data
// @DatabaseTable(tableName = "players")
// @NoArgsConstructor
// @AllArgsConstructor
// @EqualsAndHashCode(callSuper = true)
// public class Player extends Entity {
// 
//     @DatabaseField
//     private Date birthDate;
// 
//     @DatabaseField
//     private String region;
// 
//     @DatabaseField
//     private String country;
// 
//     @DatabaseField
//     private Gender gender;
// 
//     @DatabaseField(index = true)
//     private String externalId;
// 
// }
// 
// Path: src/main/java/org/cri/redmetrics/model/ProgressData.java
// @Data
// @EqualsAndHashCode(callSuper = true)
// public abstract class ProgressData extends Entity {
// 
//     @DatabaseField(
//             canBeNull = false,
//             foreign = true,
//             columnDefinition = "VARCHAR, FOREIGN KEY (\"gameVersion_id\") REFERENCES game_versions(id)")
//     private GameVersion gameVersion;
// 
//     @DatabaseField(
//             canBeNull = false,
//             foreign = true,
//             columnDefinition = "VARCHAR, FOREIGN KEY (player_id) REFERENCES players(id)")
//     private Player player;
// 
//     @DatabaseField(canBeNull = false)
//     private Date serverTime = new Date();
// 
//     @DatabaseField
//     private Date userTime;
// 
//     @DatabaseField(persisterClass = LtreePersister.class, columnDefinition = "ltree")
//     private String section;
// 
//     @DatabaseField(canBeNull = false)
//     private String type;
//     
// }
// 
// Path: src/main/java/org/cri/redmetrics/util/DateFormatter.java
// public class DateFormatter {
// 
//     // ISO 8601 Extended Format
//     private static final DateTimeFormatter ISO_DATE_FORMATTER =
//             DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZone(DateTimeZone.UTC);
// 
//     private static final DateTimeFormatter DB_DAY_DATE_FORMATTER =
//             DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").withZone(DateTimeZone.UTC);
// 
//     public static Date parseIso(String date) {
//         return ISO_DATE_FORMATTER.parseDateTime(date).toDate();
//     }
// 
//     public static String printIso(Date date) {
//         return ISO_DATE_FORMATTER.print(new DateTime(date.getTime()));
//     }
// 
//     public static Date parseDbDay(String date) {
//         return DB_DAY_DATE_FORMATTER.parseDateTime(date).toDate();
//     }
// 
//     public static String printDbDay(Date date) {
//         return DB_DAY_DATE_FORMATTER.print(new DateTime(date.getTime()));
//     }
// 
//     public static double dateToSeconds(Date date) {
//         return date.getTime() / 1000;
//     }
// 
//     public static Date secondsToDate(double seconds) {
//         return new Date((long) seconds * 1000);
//     }
// }


import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.GenericRawResults;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.Where;
import org.cri.redmetrics.model.BinCount;
import org.cri.redmetrics.model.GameVersion;
import org.cri.redmetrics.model.Player;
import org.cri.redmetrics.model.ProgressData;
import org.cri.redmetrics.util.DateFormatter;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Stream;
            long count = orm.countOf(queryBuilder.prepare());
            queryBuilder.setCountOf(false);
            return count;
        } catch (SQLException e) {
            throw new DbException(e);
        }
    }

    public List<BinCount> countResultsOverTime(Date minTime, Date maxTime, int binCount) {
        try {
            double minTimeSeconds = DateFormatter.dateToSeconds(minTime);
            double maxTimeSeconds = DateFormatter.dateToSeconds(maxTime);

            /*  Request looks like:
                select width_bucket(extract(epoch from coalesce("userTime", "serverTime")), 1449439417.264, 1449601447.176, 10) as bucket,
                    count(*)
                from events
                group by bucket
                order by bucket */
            queryBuilder.selectRaw("width_bucket(extract(epoch from \"serverTime\"), " + minTimeSeconds + ", " + maxTimeSeconds + ", " + binCount + ") as bucket",
                    "count(*) as count");
            queryBuilder.groupByRaw("bucket");

            GenericRawResults<String[]> rawResults = orm.queryRaw(queryBuilder.prepareStatementString());

            // Initialize the list of empty bins
            double timePerBucket = (maxTimeSeconds - minTimeSeconds) / binCount;
            ArrayList<BinCount> bins = new ArrayList<BinCount>(binCount);
            for(int i = 0; i < binCount; i++) {
                double bucketTime = minTimeSeconds + i * timePerBucket;
// Path: src/main/java/org/cri/redmetrics/model/BinCount.java
// public class BinCount {
//     public BinCount(Date date, long count) {
//         this.date = date;
//         this.count = count;
//     }
// 
//     public Date date;
//     public long count;
// }
// 
// Path: src/main/java/org/cri/redmetrics/model/GameVersion.java
// @Data
// @DatabaseTable(tableName = "game_versions")
// @NoArgsConstructor
// @AllArgsConstructor
// @EqualsAndHashCode(callSuper = true)
// public class GameVersion extends Entity {
// 
//     @DatabaseField(
//             canBeNull = false,
//             foreign = true,
//             columnDefinition = "VARCHAR, FOREIGN KEY (game_id) REFERENCES games(id)")
//     private Game game;
// 
//     @DatabaseField(canBeNull = false)
//     private String name;
// 
//     @DatabaseField
//     private String author;
// 
//     @DatabaseField
//     private String description;
// 
// }
// 
// Path: src/main/java/org/cri/redmetrics/model/Player.java
// @Data
// @DatabaseTable(tableName = "players")
// @NoArgsConstructor
// @AllArgsConstructor
// @EqualsAndHashCode(callSuper = true)
// public class Player extends Entity {
// 
//     @DatabaseField
//     private Date birthDate;
// 
//     @DatabaseField
//     private String region;
// 
//     @DatabaseField
//     private String country;
// 
//     @DatabaseField
//     private Gender gender;
// 
//     @DatabaseField(index = true)
//     private String externalId;
// 
// }
// 
// Path: src/main/java/org/cri/redmetrics/model/ProgressData.java
// @Data
// @EqualsAndHashCode(callSuper = true)
// public abstract class ProgressData extends Entity {
// 
//     @DatabaseField(
//             canBeNull = false,
//             foreign = true,
//             columnDefinition = "VARCHAR, FOREIGN KEY (\"gameVersion_id\") REFERENCES game_versions(id)")
//     private GameVersion gameVersion;
// 
//     @DatabaseField(
//             canBeNull = false,
//             foreign = true,
//             columnDefinition = "VARCHAR, FOREIGN KEY (player_id) REFERENCES players(id)")
//     private Player player;
// 
//     @DatabaseField(canBeNull = false)
//     private Date serverTime = new Date();
// 
//     @DatabaseField
//     private Date userTime;
// 
//     @DatabaseField(persisterClass = LtreePersister.class, columnDefinition = "ltree")
//     private String section;
// 
//     @DatabaseField(canBeNull = false)
//     private String type;
//     
// }
// 
// Path: src/main/java/org/cri/redmetrics/util/DateFormatter.java
// public class DateFormatter {
// 
//     // ISO 8601 Extended Format
//     private static final DateTimeFormatter ISO_DATE_FORMATTER =
//             DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZone(DateTimeZone.UTC);
// 
//     private static final DateTimeFormatter DB_DAY_DATE_FORMATTER =
//             DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").withZone(DateTimeZone.UTC);
// 
//     public static Date parseIso(String date) {
//         return ISO_DATE_FORMATTER.parseDateTime(date).toDate();
//     }
// 
//     public static String printIso(Date date) {
//         return ISO_DATE_FORMATTER.print(new DateTime(date.getTime()));
//     }
// 
//     public static Date parseDbDay(String date) {
//         return DB_DAY_DATE_FORMATTER.parseDateTime(date).toDate();
//     }
// 
//     public static String printDbDay(Date date) {
//         return DB_DAY_DATE_FORMATTER.print(new DateTime(date.getTime()));
//     }
// 
//     public static double dateToSeconds(Date date) {
//         return date.getTime() / 1000;
//     }
// 
//     public static Date secondsToDate(double seconds) {
//         return new Date((long) seconds * 1000);
//     }
// }


// Path: src/main/java/org/cri/redmetrics/dao/SearchQuery.java
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.GenericRawResults;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.Where;
import org.cri.redmetrics.model.BinCount;
import org.cri.redmetrics.model.GameVersion;
import org.cri.redmetrics.model.Player;
import org.cri.redmetrics.model.ProgressData;
import org.cri.redmetrics.util.DateFormatter;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Stream;

            long count = orm.countOf(queryBuilder.prepare());
            queryBuilder.setCountOf(false);
            return count;
        } catch (SQLException e) {
            throw new DbException(e);
        }
    }

    public List<BinCount> countResultsOverTime(Date minTime, Date maxTime, int binCount) {
        try {
            double minTimeSeconds = DateFormatter.dateToSeconds(minTime);
            double maxTimeSeconds = DateFormatter.dateToSeconds(maxTime);

            /*  Request looks like:
                select width_bucket(extract(epoch from coalesce("userTime", "serverTime")), 1449439417.264, 1449601447.176, 10) as bucket,
                    count(*)
                from events
                group by bucket
                order by bucket */
            queryBuilder.selectRaw("width_bucket(extract(epoch from \"serverTime\"), " + minTimeSeconds + ", " + maxTimeSeconds + ", " + binCount + ") as bucket",
                    "count(*) as count");
            queryBuilder.groupByRaw("bucket");

            GenericRawResults<String[]> rawResults = orm.queryRaw(queryBuilder.prepareStatementString());

            // Initialize the list of empty bins
            double timePerBucket = (maxTimeSeconds - minTimeSeconds) / binCount;
            ArrayList<BinCount> bins = new ArrayList<BinCount>(binCount);
            for(int i = 0; i < binCount; i++) {
                double bucketTime = minTimeSeconds + i * timePerBucket;
                bins.add(new BinCount(DateFormatter.secondsToDate(bucketTime), 0));