<commit_before>package org.arkanos.aaa.data;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Locale;

import org.arkanos.aaa.controllers.Database;

public class Training {
	private static final Training factory = new Training();
	private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

	/** SQL table name **/
	static public final String TABLE_NAME = "training";
	static public final String TABLE_NAME_GAUGE = "gauge";
	static public final String TABLE_NAME_ARROW = "arrow";

	/* Common */
	static final public String FIELD_ID = "id";
	static final public String FIELD_ARCHER = "archer";
	static final public String FIELD_DISTANCE = "distance";
	static final public String FIELD_DATE = "date";

	/* Training only */
	static final public String FIELD_ARROWS = "arrows";
	static final public String FIELD_TYPE = "type";

	/* Gauge only */
	static final public String FIELD_TARGET = "target";
	static final public String FIELD_ROUND = "round";

	/* Arrow only */
	static final public String FIELD_TRAINING_ID = "training_id";
	static final public String FIELD_END = "end";
	static final public String FIELD_VALUE = "value";

	static final public String ENDS = "ends";
	static final public String TYPE_TARGET = "target";
	static final public String TYPE_BOARD = "board";
	static final public String TYPE_GAUGED = "gauged";

	public class DailyPerformance {
		public HashMap<Float, HashMap<String, HashMap<String, Integer>>> distance_type = new HashMap<Float, HashMap<String, HashMap<String, Integer>>>();
		public HashMap<Integer, HashMap<String, HashMap<Integer, HashMap<String, Integer>>>> results = new HashMap<Integer, HashMap<String, HashMap<Integer, HashMap<String, Integer>>>>();
		public HashMap<Integer, HashMap<String, HashMap<String, Float>>> averages = new HashMap<Integer, HashMap<String, HashMap<String, Float>>>();

		public HashMap<String, HashMap<String, Integer>> technique_days = new HashMap<String, HashMap<String, Integer>>();
		public HashMap<String, Integer> technique_totals = new HashMap<String, Integer>();
		public HashMap<String, Integer> totals = new HashMap<String, Integer>();

		public HashMap<String, Integer> gauged_trainings = new HashMap<String, Integer>();
		public HashMap<String, Float> average_sum = new HashMap<String, Float>();
	}

	static public DailyPerformance compileDaily(Date from, Date to, String user) throws SQLException {
		DailyPerformance dp = factory.new DailyPerformance();

		String query = "SELECT SUM(" + FIELD_ARROWS + ") AS " + FIELD_ARROWS + ",";
		query += FIELD_DATE + ",";
		query += FIELD_TYPE + " FROM " + TABLE_NAME + " ";
		query += "WHERE " + FIELD_ARCHER + " = ? ";
		query += "AND " + FIELD_TYPE + " != ? ";
		query += "AND " + FIELD_TYPE + " != ? ";
		query += "AND " + FIELD_DATE + " >= ? ";
		query += "AND " + FIELD_DATE + " < ? ";
		query += "GROUP BY " + FIELD_DATE + "," + FIELD_TYPE + ";";
		PreparedStatement ps = Database.prepare(query);
		ps.setString(1, user);
		ps.setString(2, TYPE_TARGET);
		ps.setString(3, TYPE_BOARD);
		ps.setDate(4, Database.java2sql(from));
		ps.setDate(5, Database.java2sql(to));
		ResultSet rs = ps.executeQuery();
		// "SELECT SUM(arrows) as arrows,date,type FROM aaa.training_technique
		// WHERE archer='"+user+"' AND type != 'target' AND date >=
		// '"+sdf.format(from)+"' AND date < '"+sdf.format(to)+"' GROUP BY
		// date,type;"
		while (rs.next()) {
			int arrows = rs.getInt(FIELD_ARROWS);
			String type = rs.getString(FIELD_TYPE);
			String date = sdf.format(rs.getDate(FIELD_DATE));

			HashMap<String, Integer> parent = dp.technique_days.get(type);
			if (parent == null) {
				parent = new HashMap<String, Integer>();
				dp.technique_days.put(type, parent);
			}
			parent.put(sdf.format(rs.getDate("date")), arrows);
			if (dp.technique_totals.get(date) == null) {
				dp.technique_totals.put(date, arrows);
			} else {
				dp.technique_totals.put(date, arrows + dp.technique_totals.get(date));
			}
			if (dp.totals.get(date) == null) {
				dp.totals.put(date, arrows);
			} else {
				dp.totals.put(date, arrows + dp.totals.get(date));
			}
		}
		rs.close();

		query = "SELECT SUM(" + FIELD_ARROWS + ") AS " + FIELD_ARROWS + ",";
		query += FIELD_DATE + ",";
		query += FIELD_DISTANCE + ",";
		query += FIELD_TYPE + " FROM " + TABLE_NAME + " ";
		query += "WHERE " + FIELD_ARCHER + " = ? ";
		query += "AND (" + FIELD_TYPE + " = ? ";
		query += "OR " + FIELD_TYPE + " = ?) ";
		query += "AND " + FIELD_DATE + " >= ? ";
		query += "AND " + FIELD_DATE + " < ? ";
		query += "GROUP BY " + FIELD_DISTANCE + "," + FIELD_DATE + "," + FIELD_TYPE + ";";
		ps = Database.prepare(query);
		ps.setString(1, user);
		ps.setString(2, TYPE_TARGET);
		ps.setString(3, TYPE_BOARD);
		ps.setDate(4, Database.java2sql(from));
		ps.setDate(5, Database.java2sql(to));
		rs = ps.executeQuery();
		// "SELECT SUM(arrows) as arrows,distance,date,type FROM
		// aaa.training_technique WHERE archer='"+user+"' AND type = 'target'
		// AND date >= '"+sdf.format(from)+"' AND date < '"+sdf.format(to)+"'
		// GROUP BY distance,date,type;"
		while (rs.next()) {
			int arrows = rs.getInt(FIELD_ARROWS);
			float distance = rs.getFloat(FIELD_DISTANCE);
			String type = rs.getString(FIELD_TYPE);
			String date = sdf.format(rs.getDate(FIELD_DATE));

			HashMap<String, HashMap<String, Integer>> grandparent = dp.distance_type.get(distance);
			if (grandparent == null) {
				grandparent = new HashMap<String, HashMap<String, Integer>>();
				dp.distance_type.put(distance, grandparent);
			}
			HashMap<String, Integer> parent = grandparent.get(type);
			if (parent == null) {
				parent = new HashMap<String, Integer>();
				grandparent.put(type, parent);
			}
			parent.put(date, arrows);
			if (dp.technique_totals.get(date) == null) {
				dp.technique_totals.put(date, arrows);
			} else {
				dp.technique_totals.put(date, arrows + dp.technique_totals.get(date));
			}
			if (dp.totals.get(date) == null) {
				dp.totals.put(date, arrows);
			} else {
				dp.totals.put(date, arrows + dp.totals.get(date));
			}
		}
		rs.close();

		query = "SELECT COUNT(" + FIELD_VALUE + ") AS " + FIELD_ARROWS + ",";
		query += FIELD_DATE + ",";
		query += FIELD_DISTANCE + " FROM " + TABLE_NAME_ARROW + " ";
		query += "LEFT JOIN " + TABLE_NAME_GAUGE + " ";
		query += "ON " + FIELD_ID + " = " + FIELD_TRAINING_ID + " ";
		query += "WHERE " + FIELD_ARCHER + " = ? ";
		query += "AND " + FIELD_DATE + " >= ? ";
		query += "AND " + FIELD_DATE + " < ? ";
		query += "GROUP BY " + FIELD_DISTANCE + "," + FIELD_DATE + ";";
		ps = Database.prepare(query);
		ps.setString(1, user);
		// TODO use this in all dates (avoid Database.sdf)
		ps.setDate(2, Database.java2sql(from));
		ps.setDate(3, Database.java2sql(to));
		rs = ps.executeQuery();
		// "SELECT COUNT(value) as arrows,date,distance FROM arrow LEFT JOIN
		// training_target ON id = training_id WHERE archer='"+user+"' AND date
		// >= '"+sdf.format(from)+"' AND date < '"+sdf.format(to)+"' GROUP BY
		// date,distance;"
		while (rs.next()) {
			int arrows = rs.getInt(FIELD_ARROWS);
			float distance = rs.getFloat(FIELD_DISTANCE);
			String date = sdf.format(rs.getDate(FIELD_DATE));
			HashMap<String, HashMap<String, Integer>> grandparent = dp.distance_type.get(distance);
			if (grandparent == null) {
				grandparent = new HashMap<String, HashMap<String, Integer>>();
				dp.distance_type.put(distance, grandparent);
			}
			HashMap<String, Integer> parent = grandparent.get(TYPE_GAUGED);
			if (parent == null) {
				parent = new HashMap<String, Integer>();
				grandparent.put(TYPE_GAUGED, parent);
			}
			parent.put(date, arrows);
			if (dp.totals.get(date) == null) {
				dp.totals.put(date, arrows);
			} else {
				dp.totals.put(date, arrows + dp.totals.get(date));
			}
		}
		rs.close();

		query = "SELECT SUM(" + FIELD_VALUE + ") AS result,";
		query += FIELD_DATE + ",";
		query += FIELD_ID + ",";
		query += FIELD_TARGET + ",";
		query += FIELD_DISTANCE + " FROM " + TABLE_NAME_GAUGE + " ";
		query += "LEFT JOIN " + TABLE_NAME_ARROW + " ";
		query += "ON " + FIELD_ID + " = " + FIELD_TRAINING_ID + " ";
		query += "WHERE " + FIELD_ARCHER + " = ? ";
		query += "AND " + FIELD_DATE + " >= ? ";
		query += "AND " + FIELD_DATE + " < ? ";
		query += "GROUP BY " + FIELD_ID + ";";
		ps = Database.prepare(query);
		ps.setString(1, user);
		ps.setDate(2, Database.java2sql(from));
		ps.setDate(3, Database.java2sql(to));
		rs = ps.executeQuery();
		// "SELECT date,distance,class,id,SUM(value) as result FROM
		// training_target LEFT JOIN arrow ON id = training_id WHERE
		// archer='"+user+"' AND date >= '"+sdf.format(from)+"' AND date <
		// '"+sdf.format(to)+"' GROUP BY id;"
		HashMap<String, Integer> result_order = new HashMap<String, Integer>();
		while (rs.next()) {
			int distance = rs.getInt(FIELD_DISTANCE);
			String target = rs.getString(FIELD_TARGET);
			String date = sdf.format(rs.getDate(FIELD_DATE));
			int result = rs.getInt("result");

			HashMap<String, HashMap<Integer, HashMap<String, Integer>>> greatgrandparent = dp.results.get(distance);
			if (greatgrandparent == null) {
				greatgrandparent = new HashMap<String, HashMap<Integer, HashMap<String, Integer>>>();
				dp.results.put(distance, greatgrandparent);
			}
			HashMap<Integer, HashMap<String, Integer>> grandparent = greatgrandparent.get(target);
			if (grandparent == null) {
				grandparent = new HashMap<Integer, HashMap<String, Integer>>();
				greatgrandparent.put(target, grandparent);
			}

			/** ID to order magic **/
			Integer order = result_order.get(distance + target + date);
			if (order == null) {
				order = 1;
			}

			result_order.put(distance + target + date, order);
			HashMap<String, Integer> parent = grandparent.get(order);
			if (parent == null) {
				parent = new HashMap<String, Integer>();
				grandparent.put(order, parent);
			}
			order += 1;
			parent.put(date, result);
		}
		rs.close();

		query = "SELECT AVG(" + FIELD_VALUE + ") AS average,";
		query += FIELD_DATE + ",";
		query += FIELD_ID + ",";
		query += FIELD_TARGET + ",";
		query += FIELD_DISTANCE + " FROM " + TABLE_NAME_GAUGE + " ";
		query += "LEFT JOIN " + TABLE_NAME_ARROW + " ";
		query += "ON " + FIELD_ID + " = " + FIELD_TRAINING_ID + " ";
		query += "WHERE " + FIELD_ARCHER + " = ? ";
		query += "AND " + FIELD_DATE + " >= ? ";
		query += "AND " + FIELD_DATE + " < ? ";
		query += "GROUP BY " + FIELD_DATE + "," + FIELD_TARGET + "," + FIELD_DISTANCE + ";";
		ps = Database.prepare(query);
		ps.setString(1, user);
		ps.setDate(2, Database.java2sql(from));
		ps.setDate(3, Database.java2sql(to));
		rs = ps.executeQuery();
		// "SELECT date,distance,class,id,AVG(value) AS average FROM
		// training_target LEFT JOIN arrow ON id = training_id WHERE
		// archer='"+user+"' AND date >= '"+sdf.format(from)+"' AND date <<commit_msg>Fixing regression with multiple rounds.<commit_after>package org.arkanos.aaa.data;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Locale;

import org.arkanos.aaa.controllers.Database;

public class Training {
	private static final Training factory = new Training();
	private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

	/** SQL table name **/
	static public final String TABLE_NAME = "training";
	static public final String TABLE_NAME_GAUGE = "gauge";
	static public final String TABLE_NAME_ARROW = "arrow";

	/* Common */
	static final public String FIELD_ID = "id";
	static final public String FIELD_ARCHER = "archer";
	static final public String FIELD_DISTANCE = "distance";
	static final public String FIELD_DATE = "date";

	/* Training only */
	static final public String FIELD_ARROWS = "arrows";
	static final public String FIELD_TYPE = "type";

	/* Gauge only */
	static final public String FIELD_TARGET = "target";
	static final public String FIELD_ROUND = "round";

	/* Arrow only */
	static final public String FIELD_TRAINING_ID = "training_id";
	static final public String FIELD_END = "end";
	static final public String FIELD_VALUE = "value";

	static final public String ENDS = "ends";
	static final public String TYPE_TARGET = "target";
	static final public String TYPE_BOARD = "board";
	static final public String TYPE_GAUGED = "gauged";

	public class DailyPerformance {
		public HashMap<Float, HashMap<String, HashMap<String, Integer>>> distance_type = new HashMap<Float, HashMap<String, HashMap<String, Integer>>>();
		public HashMap<Integer, HashMap<String, HashMap<Integer, HashMap<String, Integer>>>> results = new HashMap<Integer, HashMap<String, HashMap<Integer, HashMap<String, Integer>>>>();
		public HashMap<Integer, HashMap<String, HashMap<String, Float>>> averages = new HashMap<Integer, HashMap<String, HashMap<String, Float>>>();

		public HashMap<String, HashMap<String, Integer>> technique_days = new HashMap<String, HashMap<String, Integer>>();
		public HashMap<String, Integer> technique_totals = new HashMap<String, Integer>();
		public HashMap<String, Integer> totals = new HashMap<String, Integer>();

		public HashMap<String, Integer> gauged_trainings = new HashMap<String, Integer>();
		public HashMap<String, Float> average_sum = new HashMap<String, Float>();
	}

	static public DailyPerformance compileDaily(Date from, Date to, String user) throws SQLException {
		DailyPerformance dp = factory.new DailyPerformance();

		String query = "SELECT SUM(" + FIELD_ARROWS + ") AS " + FIELD_ARROWS + ",";
		query += FIELD_DATE + ",";
		query += FIELD_TYPE + " FROM " + TABLE_NAME + " ";
		query += "WHERE " + FIELD_ARCHER + " = ? ";
		query += "AND " + FIELD_TYPE + " != ? ";
		query += "AND " + FIELD_TYPE + " != ? ";
		query += "AND " + FIELD_DATE + " >= ? ";
		query += "AND " + FIELD_DATE + " < ? ";
		query += "GROUP BY " + FIELD_DATE + "," + FIELD_TYPE + ";";
		PreparedStatement ps = Database.prepare(query);
		ps.setString(1, user);
		ps.setString(2, TYPE_TARGET);
		ps.setString(3, TYPE_BOARD);
		ps.setDate(4, Database.java2sql(from));
		ps.setDate(5, Database.java2sql(to));
		ResultSet rs = ps.executeQuery();
		// "SELECT SUM(arrows) as arrows,date,type FROM aaa.training_technique
		// WHERE archer='"+user+"' AND type != 'target' AND date >=
		// '"+sdf.format(from)+"' AND date < '"+sdf.format(to)+"' GROUP BY
		// date,type;"
		while (rs.next()) {
			int arrows = rs.getInt(FIELD_ARROWS);
			String type = rs.getString(FIELD_TYPE);
			String date = sdf.format(rs.getDate(FIELD_DATE));

			HashMap<String, Integer> parent = dp.technique_days.get(type);
			if (parent == null) {
				parent = new HashMap<String, Integer>();
				dp.technique_days.put(type, parent);
			}
			parent.put(sdf.format(rs.getDate("date")), arrows);
			if (dp.technique_totals.get(date) == null) {
				dp.technique_totals.put(date, arrows);
			} else {
				dp.technique_totals.put(date, arrows + dp.technique_totals.get(date));
			}
			if (dp.totals.get(date) == null) {
				dp.totals.put(date, arrows);
			} else {
				dp.totals.put(date, arrows + dp.totals.get(date));
			}
		}
		rs.close();

		query = "SELECT SUM(" + FIELD_ARROWS + ") AS " + FIELD_ARROWS + ",";
		query += FIELD_DATE + ",";
		query += FIELD_DISTANCE + ",";
		query += FIELD_TYPE + " FROM " + TABLE_NAME + " ";
		query += "WHERE " + FIELD_ARCHER + " = ? ";
		query += "AND (" + FIELD_TYPE + " = ? ";
		query += "OR " + FIELD_TYPE + " = ?) ";
		query += "AND " + FIELD_DATE + " >= ? ";
		query += "AND " + FIELD_DATE + " < ? ";
		query += "GROUP BY " + FIELD_DISTANCE + "," + FIELD_DATE + "," + FIELD_TYPE + ";";
		ps = Database.prepare(query);
		ps.setString(1, user);
		ps.setString(2, TYPE_TARGET);
		ps.setString(3, TYPE_BOARD);
		ps.setDate(4, Database.java2sql(from));
		ps.setDate(5, Database.java2sql(to));
		rs = ps.executeQuery();
		// "SELECT SUM(arrows) as arrows,distance,date,type FROM
		// aaa.training_technique WHERE archer='"+user+"' AND type = 'target'
		// AND date >= '"+sdf.format(from)+"' AND date < '"+sdf.format(to)+"'
		// GROUP BY distance,date,type;"
		while (rs.next()) {
			int arrows = rs.getInt(FIELD_ARROWS);
			float distance = rs.getFloat(FIELD_DISTANCE);
			String type = rs.getString(FIELD_TYPE);
			String date = sdf.format(rs.getDate(FIELD_DATE));

			HashMap<String, HashMap<String, Integer>> grandparent = dp.distance_type.get(distance);
			if (grandparent == null) {
				grandparent = new HashMap<String, HashMap<String, Integer>>();
				dp.distance_type.put(distance, grandparent);
			}
			HashMap<String, Integer> parent = grandparent.get(type);
			if (parent == null) {
				parent = new HashMap<String, Integer>();
				grandparent.put(type, parent);
			}
			parent.put(date, arrows);
			if (dp.technique_totals.get(date) == null) {
				dp.technique_totals.put(date, arrows);
			} else {
				dp.technique_totals.put(date, arrows + dp.technique_totals.get(date));
			}
			if (dp.totals.get(date) == null) {
				dp.totals.put(date, arrows);
			} else {
				dp.totals.put(date, arrows + dp.totals.get(date));
			}
		}
		rs.close();

		query = "SELECT COUNT(" + FIELD_VALUE + ") AS " + FIELD_ARROWS + ",";
		query += FIELD_DATE + ",";
		query += FIELD_DISTANCE + " FROM " + TABLE_NAME_ARROW + " ";
		query += "LEFT JOIN " + TABLE_NAME_GAUGE + " ";
		query += "ON " + FIELD_ID + " = " + FIELD_TRAINING_ID + " ";
		query += "WHERE " + FIELD_ARCHER + " = ? ";
		query += "AND " + FIELD_DATE + " >= ? ";
		query += "AND " + FIELD_DATE + " < ? ";
		query += "GROUP BY " + FIELD_DISTANCE + "," + FIELD_DATE + ";";
		ps = Database.prepare(query);
		ps.setString(1, user);
		// TODO use this in all dates (avoid Database.sdf)
		ps.setDate(2, Database.java2sql(from));
		ps.setDate(3, Database.java2sql(to));
		rs = ps.executeQuery();
		// "SELECT COUNT(value) as arrows,date,distance FROM arrow LEFT JOIN
		// training_target ON id = training_id WHERE archer='"+user+"' AND date
		// >= '"+sdf.format(from)+"' AND date < '"+sdf.format(to)+"' GROUP BY
		// date,distance;"
		while (rs.next()) {
			int arrows = rs.getInt(FIELD_ARROWS);
			float distance = rs.getFloat(FIELD_DISTANCE);
			String date = sdf.format(rs.getDate(FIELD_DATE));
			HashMap<String, HashMap<String, Integer>> grandparent = dp.distance_type.get(distance);
			if (grandparent == null) {
				grandparent = new HashMap<String, HashMap<String, Integer>>();
				dp.distance_type.put(distance, grandparent);
			}
			HashMap<String, Integer> parent = grandparent.get(TYPE_GAUGED);
			if (parent == null) {
				parent = new HashMap<String, Integer>();
				grandparent.put(TYPE_GAUGED, parent);
			}
			parent.put(date, arrows);
			if (dp.totals.get(date) == null) {
				dp.totals.put(date, arrows);
			} else {
				dp.totals.put(date, arrows + dp.totals.get(date));
			}
		}
		rs.close();

		query = "SELECT SUM(" + FIELD_VALUE + ") AS result,";
		query += FIELD_DATE + ",";
		query += FIELD_ID + ",";
		query += FIELD_TARGET + ",";
		query += FIELD_ROUND + ",";
		query += FIELD_DISTANCE + " FROM " + TABLE_NAME_GAUGE + " ";
		query += "LEFT JOIN " + TABLE_NAME_ARROW + " ";
		query += "ON " + FIELD_ID + " = " + FIELD_TRAINING_ID + " ";
		query += "WHERE " + FIELD_ARCHER + " = ? ";
		query += "AND " + FIELD_DATE + " >= ? ";
		query += "AND " + FIELD_DATE + " < ? ";
		query += "GROUP BY " + FIELD_ID + "," + FIELD_ROUND + ";";
		ps = Database.prepare(query);
		ps.setString(1, user);
		ps.setDate(2, Database.java2sql(from));
		ps.setDate(3, Database.java2sql(to));
		rs = ps.executeQuery();
		// "SELECT date,distance,class,id,SUM(value) as result FROM
		// training_target LEFT JOIN arrow ON id = training_id WHERE
		// archer='"+user+"' AND date >= '"+sdf.format(from)+"' AND date <
		// '"+sdf.format(to)+"' GROUP BY id;"
		while (rs.next()) {
			int distance = rs.getInt(FIELD_DISTANCE);
			String target = rs.getString(FIELD_TARGET);
			String date = sdf.format(rs.getDate(FIELD_DATE));
			int result = rs.getInt("result");
			int round = rs.getInt(FIELD_ROUND);

			HashMap<String, HashMap<Integer, HashMap<String, Integer>>> greatgrandparent = dp.results.get(distance);
			if (greatgrandparent == null) {
				greatgrandparent = new HashMap<String, HashMap<Integer, HashMap<String, Integer>>>();
				dp.results.put(distance, greatgrandparent);
			}
			HashMap<Integer, HashMap<String, Integer>> grandparent = greatgrandparent.get(target);
			if (grandparent == null) {
				grandparent = new HashMap<Integer, HashMap<String, Integer>>();
				greatgrandparent.put(target, grandparent);
			}

			HashMap<String, Integer> parent = grandparent.get(round);
			if (parent == null) {
				parent = new HashMap<String, Integer>();
				grandparent.put(round, parent);
			}
			parent.put(date, result);
		}
		rs.close();

		query = "SELECT AVG(" + FIELD_VALUE + ") AS average,";
		query += FIELD_DATE + ",";
		query += FIELD_ID + ",";
		query += FIELD_TARGET + ",";
		query += FIELD_DISTANCE + " FROM " + TABLE_NAME_GAUGE + " ";
		query += "LEFT JOIN " + TABLE_NAME_ARROW + " ";
		query += "ON " + FIELD_ID + " = " + FIELD_TRAINING_ID + " ";
		query += "WHERE " + FIELD_ARCHER + " = ? ";
		query += "AND " + FIELD_DATE + " >= ? ";
		query += "AND " + FIELD_DATE + " < ? ";
		query += "GROUP BY " + FIELD_DATE + "," + FIELD_TARGET + "," + FIELD_DISTANCE + ";";
		ps = Database.prepare(query);
		ps.setString(1, user);
		ps.setDate(2, Database.java2sql(from));
		ps.setDate(3, Database.java2sql(to));
		rs = ps.executeQuery();
		// "SELECT date,distance,class,id,AVG(value) AS average FROM
		// training_target LEFT JOIN arrow ON id = training_id WHERE
		// archer='"+user+"' AND date >= '"+sdf.format(from)+"' AND date <
{'fraction_non_alphanumeric': 0.16611310796669548, 'fraction_numerical': 0.002729878520405842, 'mean_word_length': 4.017119379137183, 'pattern_counts': {'":': 0, '<': 141, '<?xml version=': 0, '>': 141, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6195297', 'n_tokens_mistral': 8231, 'n_tokens_neox': 7373, 'n_words': 1682}