import java.io.IOException;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.PriorityQueue;
import java.util.stream.Collectors;

public class IntraDayCompare {

	private static final DecimalFormat df = new DecimalFormat("#.##%");  // % numbers
	private static final DecimalFormat dfI = new DecimalFormat("#,###"); // Integers
	private static final int TICKER = 0, PER = 1, DATE = 2, TIME = 3,
		                     OPEN = 4, HIGH = 5, LOW = 6,
		                     CLOSE = 7, VOL = 8, OPENINT = 9;
	private static final int THE_DAY = 20250409;
	private static final int PRIOR_DAY = 20250408;
	private static final int PREV_APRIL_DAYS = 6;
	private static final int POST_APRIL_DAYS = 6;
	
	private static final double TSLA_PER = .037d; 
	private static int tslaCurrentDate = 0;
	private static Data tslaCurrentData = null;
	private static double tslaBeforeBest = -100d;
	private static int tslaBeforeBetter = 0;
	private static int tslaBestBeforeDate = 0;
	private static double tslaAfterBest = -100d;
	private static int tslaBestAfterDate = 0;
	private static int tslaAfterBetter = 0;
	
	private static final double DJT_PER = .0752d;	
	private static int djtCurrentDate = 0;
	private static Data djtCurrentData = null;
	private static double djtBeforeBest = -100d;
	private static int djtBeforeBetter = 0;
	private static int djtBestBeforeDate = 0;
	private static double djtAfterBest = -100d;
	private static int djtBestAfterDate = 0;
	private static int djtAfterBetter = 0;
	
	// “THIS IS A GREAT TIME TO BUY!!! DJT,” he wrote on his social media 
	// platform Truth Social at 9:37 a.m.	  
	private static final int ANNOUNCE_TIME = 200000;
	// one day before days during period
	private static final HashMap<String, Data> prevDayDuring = new HashMap<String, Data>();
	// one day before days after announcement
	private static final HashMap<String, Data> prevDayAfter = new HashMap<String, Data>();
	// before day during post time 
	private static final HashMap<String, Data> aprilDuring = new HashMap<String, Data>();
	// before day after announce time 
	private static final HashMap<String, Data> aprilAfter = new HashMap<String, Data>();
	// during day during post time 
	private static final HashMap<String, Data> dayDuring = new HashMap<String, Data>();
	// during day after announce time 
	private static final HashMap<String, Data> dayAfter = new HashMap<String, Data>();
	// after the day during post time
	private static final HashMap<String, Data> postDuring = new HashMap<String, Data>();
	// after the day during announce time
	private static final HashMap<String, Data> postAfter = new HashMap<String, Data>();
		 
	public static void main(String... args) {
		String[] paths = new String[] {
			"/Users/mjh/data/hourly/us/nyse stocks",
			"/Users/mjh/data/hourly/us/nasdaq stocks"
		};
		for (String path : paths) {
			Path startingDir = Paths.get(path);
			try {
				Files.walkFileTree(startingDir, new SimpleFileVisitor<Path>() {
					@Override
					public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
						if (file.getFileName().toString().startsWith(".")) {
							return FileVisitResult.CONTINUE;
						}
						String fileName = file.getFileName().toString();
						try {
							doFile(file);
						}
						catch (Exception ex) { 
							System.out.println("file " + fileName + " errored");
							if (fileName.equals("tsla.us.txt")) {
								ex.printStackTrace();
							}
							//ex.printStackTrace(); 
						}
						return FileVisitResult.CONTINUE;
					}

					@Override
					public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
						System.out.println("Directory: " + dir);
						return FileVisitResult.CONTINUE;
					}

					@Override
					public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
						System.err.println("Failed to access file: " + file + ", error: " + exc.getMessage());
						return FileVisitResult.CONTINUE;
					}

					@Override
					public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
						 if (exc != null) {
							System.err.println("Error during directory traversal: " + dir + ", error: " + exc.getMessage());
						}
						return FileVisitResult.CONTINUE;
					}
				});
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		Map<String, Data> map = sortByValue(prevDayDuring,false);
		int cnt = 0;
		System.out.println("* ------------------------------------------------- *");
		System.out.println("The previous day during time of Truth Social post...");
		System.out.println("* ------------------------------------------------- *");
		System.out.println("*-- Top 10 --*");
		for (String ticker : map.keySet()) {
			Data data = map.get(ticker);
			String changePer = df.format(data.avgChangePercent());
			String volume = dfI.format(data.totalVol());
			System.out.println("\t" + ticker + ": (" + changePer + "). Volume: " + volume);
			cnt += 1;
			if (cnt > 9) break;
		}
		System.out.println("");
		System.out.println("*** Stocks mentioned in article");
		System.out.println("\tTSLA " + info(map.get("TSLA.US")));
		System.out.println("\tDJT " + info(map.get("DJT.US")));
		System.out.println("");
		System.out.println("*** Marjorie Taylor Greene purchases 04/08-04/09 -");
		System.out.println("\tADBE " + info(map.get("ADBE.US")));
		System.out.println("\tAMD " + info(map.get("AMD.US")));
		System.out.println("\tAMZN " + info(map.get("AMZN.US")));
		System.out.println("\tAAPL " + info(map.get("AAPL.US")));
		System.out.println("\tAMAT " + info(map.get("AMAT.US")));
		System.out.println("\tASML " + info(map.get("ASML.US")));
		System.out.println("\tBX " + info(map.get("BX.US")));
		System.out.println("\tCMI " + info(map.get("CMI.US")));
		System.out.println("\tDVN " + info(map.get("DVN.US")));
		System.out.println("\tFDX " + info(map.get("FDX.US")));
		System.out.println("\tJPM " + info(map.get("JPM.US")));
		System.out.println("\tLULU " + info(map.get("LULU.US")));
		System.out.println("\tMRK " + info(map.get("MRK.US")));
		System.out.println("\tNKE " + info(map.get("NKE.US")));
		System.out.println("\tNVDA " + info(map.get("NVDA.US")));
		System.out.println("\tPLTR " + info(map.get("PLTR.US")));
		System.out.println("\tQCOM " + info(map.get("QCOM.US")));
		System.out.println("\tSCCO " + info(map.get("SCCO.US")));
		System.out.println("\tAlso TSLA - Tesla");	
		System.out.println("");
		map = sortByValue(prevDayAfter,false);
		cnt = 0;
		System.out.println("* ----------------------------------------------------- *");
		System.out.println("The previous day after time of 10% tariff announcement...");
		System.out.println("* ----------------------------------------------------- *");
		System.out.println("*-- Top 10 --*");
		for (String ticker : map.keySet()) {
			Data data = map.get(ticker);
			String changePer = df.format(data.avgChangePercent());
			String volume = dfI.format(data.totalVol());
			System.out.println("\t" + ticker + ": (" + changePer + "). Volume: " + volume);
			cnt += 1;
			if (cnt > 9) break;
		}
		System.out.println("");
		System.out.println("*** Stocks mentioned in article");
		System.out.println("\tTSLA " + info(map.get("TSLA.US")));
		System.out.println("\tDJT " + info(map.get("DJT.US")));
		System.out.println("");
		System.out.println("*** Marjorie Taylor Greene purchases 04/08-04/09 -");
		System.out.println("\tADBE " + info(map.get("ADBE.US")));
		System.out.println("\tAMD " + info(map.get("AMD.US")));
		System.out.println("\tAMZN " + info(map.get("AMZN.US")));
		System.out.println("\tAAPL " + info(map.get("AAPL.US")));
		System.out.println("\tAMAT " + info(map.get("AMAT.US")));
		System.out.println("\tASML " + info(map.get("ASML.US")));
		System.out.println("\tBX " + info(map.get("BX.US")));
		System.out.println("\tCMI " + info(map.get("CMI.US")));
		System.out.println("\tDVN " + info(map.get("DVN.US")));
		System.out.println("\tFDX " + info(map.get("FDX.US")));
		System.out.println("\tJPM " + info(map.get("JPM.US")));
		System.out.println("\tLULU " + info(map.get("LULU.US")));
		System.out.println("\tMRK " + info(map.get("MRK.US")));
		System.out.println("\tNKE " + info(map.get("NKE.US")));
		System.out.println("\tNVDA " + info(map.get("NVDA.US")));
		System.out.println("\tPLTR " + info(map.get("PLTR.US")));
		System.out.println("\tQCOM " + info(map.get("QCOM.US")));
		System.out.println("\tSCCO " + info(map.get("SCCO.US")));
		System.out.println("\tAlso TSLA - Tesla");	
		System.out.println("");
		map = sortByValue(aprilDuring,false);
		cnt = 0;
		System.out.println("* ------------------------------------------------ *");
		System.out.println("April prior days during time of Truth Social post...");
		System.out.println("* ------------------------------------------------ *");
		System.out.println("*-- Top 10 --*");
		for (String ticker : map.keySet()) {
			Data data = map.get(ticker);
			String changePer = df.format(data.avgChangePercent());
			String volume = dfI.format(data.totalVol());
			System.out.println("\t" + ticker + ": (" + changePer + "). Volume: " + volume);
			cnt += 1;
			if (cnt > 9) break;
		}
		System.out.println("");
		System.out.println("*** Stocks mentioned in article");
		System.out.print("\tTSLA " + info(map.get("TSLA.US")));
		System.out.println(" Average Volume " + dfI.format(map.get("TSLA.US").totalVol()/PREV_APRIL_DAYS));
		System.out.print("\tDJT " + info(map.get("DJT.US")));
		System.out.println(" Average Volume " + dfI.format(map.get("DJT.US").totalVol()/PREV_APRIL_DAYS)); 
		System.out.println("");
		System.out.println("TSLA best return % in prior April days " + df.format(tslaBeforeBest));
		System.out.println("TSLA best date " + tslaBestBeforeDate);
		System.out.println("TSLA number of prior April days better " + tslaBeforeBetter);
		System.out.println("DJT best return % in prior April days " + df.format(djtBeforeBest));
		System.out.println("DJT best date " + djtBestBeforeDate); 
		System.out.println("DJT number of prior April days better " + djtBeforeBetter);
		System.out.println("");
		System.out.println("*** Marjorie Taylor Greene purchases 04/08-04/09 -");
		System.out.println("\tADBE " + info(map.get("ADBE.US")));
		System.out.println("\tAMD " + info(map.get("AMD.US")));
		System.out.println("\tAMZN " + info(map.get("AMZN.US")));
		System.out.println("\tAAPL " + info(map.get("AAPL.US")));
		System.out.println("\tAMAT " + info(map.get("AMAT.US")));
		System.out.println("\tASML " + info(map.get("ASML.US")));
		System.out.println("\tBX " + info(map.get("BX.US")));
		System.out.println("\tCMI " + info(map.get("CMI.US")));
		System.out.println("\tDVN " + info(map.get("DVN.US")));
		System.out.println("\tFDX " + info(map.get("FDX.US")));
		System.out.println("\tJPM " + info(map.get("JPM.US")));
		System.out.println("\tLULU " + info(map.get("LULU.US")));
		System.out.println("\tMRK " + info(map.get("MRK.US")));
		System.out.println("\tNKE " + info(map.get("NKE.US")));
		System.out.println("\tNVDA " + info(map.get("NVDA.US")));
		System.out.println("\tPLTR " + info(map.get("PLTR.US")));
		System.out.println("\tQCOM " + info(map.get("QCOM.US")));
		System.out.println("\tSCCO " + info(map.get("SCCO.US")));
		System.out.println("\tAlso TSLA - Tesla");	
		System.out.println("");
		map = sortByValue(aprilAfter,false);
		cnt = 0;
		System.out.println("* ----------------------------------------------------- *");
		System.out.println("April prior days after time of 10% tariff announcement...");
		System.out.println("* ----------------------------------------------------- *");
		System.out.println("*-- Top 10 --*");
		for (String ticker : map.keySet()) {
			Data data = map.get(ticker);
			String changePer = df.format(data.avgChangePercent());
			String volume = dfI.format(data.totalVol());
			System.out.println("\t" + ticker + ": (" + changePer + "). Volume: " + volume);
			cnt += 1;
			if (cnt > 9) break;
		}
		System.out.println("");
		System.out.println("*** Stocks mentioned in article");
		System.out.println("\tTSLA " + info(map.get("TSLA.US")));
		System.out.println("\tDJT " + info(map.get("DJT.US")));
		System.out.println("");
		System.out.println("*** Marjorie Taylor Greene purchases 04/08-04/09 -");
		System.out.println("\tADBE " + info(map.get("ADBE.US")));
		System.out.println("\tAMD " + info(map.get("AMD.US")));
		System.out.println("\tAMZN " + info(map.get("AMZN.US")));
		System.out.println("\tAAPL " + info(map.get("AAPL.US")));
		System.out.println("\tAMAT " + info(map.get("AMAT.US")));
		System.out.println("\tASML " + info(map.get("ASML.US")));
		System.out.println("\tBX " + info(map.get("BX.US")));
		System.out.println("\tCMI " + info(map.get("CMI.US")));
		System.out.println("\tDVN " + info(map.get("DVN.US")));
		System.out.println("\tFDX " + info(map.get("FDX.US")));
		System.out.println("\tJPM " + info(map.get("JPM.US")));
		System.out.println("\tLULU " + info(map.get("LULU.US")));
		System.out.println("\tMRK " + info(map.get("MRK.US")));
		System.out.println("\tNKE " + info(map.get("NKE.US")));
		System.out.println("\tNVDA " + info(map.get("NVDA.US")));
		System.out.println("\tPLTR " + info(map.get("PLTR.US")));
		System.out.println("\tQCOM " + info(map.get("QCOM.US")));
		System.out.println("\tSCCO " + info(map.get("SCCO.US")));
		System.out.println("\tAlso TSLA - Tesla");	
		System.out.println("");
		map = sortByValue(dayDuring,false);
		cnt = 0;
		System.out.println("* ---------------------------------------------- *");
		System.out.println("The actual day during time of Truth Social post...");
		System.out.println("* ---------------------------------------------- *");
		System.out.println("*-- Top 10 --*");
		for (String ticker : map.keySet()) {
			Data data = map.get(ticker);			
			String changePer = df.format(data.avgChangePercent());
			String volume = dfI.format(data.totalVol());
			System.out.println("\t" + ticker + ": (" + changePer + "). Volume: " + volume);
			cnt += 1;
			if (cnt > 9) break;
		}
		System.out.println("");
		System.out.println("TSLA " + map.get("TSLA.US"));
		System.out.println("DJT " + map.get("DJT.US"));
		System.out.println("");
		System.out.println("*** Marjorie Taylor Greene purchases 04/08-04/09 -");
		System.out.println("\tADBE " + info(map.get("ADBE.US"),true,
											prevDayDuring.get("ADBE.US"),
											aprilDuring.get("ADBE.US")));
		System.out.println("\tAMD " + info(map.get("AMD.US"),true,
											prevDayDuring.get("AMD.US"),
											aprilDuring.get("AMD.US")));
		System.out.println("\tAMZN " + info(map.get("AMZN.US"),true,
											prevDayDuring.get("AMZN.US"),
											aprilDuring.get("AMZN.US")));
		System.out.println("\tAAPL " + info(map.get("AAPL.US"),true,
											prevDayDuring.get("AAPL.US"),
											aprilDuring.get("AAPL.US")));
		System.out.println("\tAMAT " + info(map.get("AMAT.US"),true,
											prevDayDuring.get("AMAT.US"),
											aprilDuring.get("AMAT.US")));
		System.out.println("\tASML " + info(map.get("ASML.US"),true,
											prevDayDuring.get("ASML.US"),
											aprilDuring.get("ASML.US")));
		System.out.println("\tBX " + info(map.get("BX.US"),true,
										  prevDayDuring.get("BX.US"),
										  aprilDuring.get("BX.US")));
		System.out.println("\tCMI " + info(map.get("CMI.US"),true,
										  prevDayDuring.get("CMI.US"),
										  aprilDuring.get("CMI.US")));
		System.out.println("\tDVN " + info(map.get("DVN.US"),true,
										   prevDayDuring.get("DVN.US"),
										   aprilDuring.get("DVN.US")));
		System.out.println("\tFDX " + info(map.get("FDX.US"),true,
										   prevDayDuring.get("FDX.US"),
										   aprilDuring.get("FDX.US")));
		System.out.println("\tJPM " + info(map.get("JPM.US"),true,
										   prevDayDuring.get("JPM.US"),
										   aprilDuring.get("JPM.US")));
		System.out.println("\tLULU " + info(map.get("LULU.US"),true,
											prevDayDuring.get("LULU.US"),
											aprilDuring.get("LULU.US")));
		System.out.println("\tMRK " + info(map.get("MRK.US"),true,
										   prevDayDuring.get("MRK.US"),
										   aprilDuring.get("MRK.US")));
		System.out.println("\tNKE " + info(map.get("NKE.US"),true,
										   prevDayDuring.get("NKE.US"),
										   aprilDuring.get("NKE.US")));
		System.out.println("\tNVDA " + info(map.get("NVDA.US"),true,
											prevDayDuring.get("NVDA.US"),
											aprilDuring.get("NVDA.US")));
		System.out.println("\tPLTR " + info(map.get("PLTR.US"),true,
											prevDayDuring.get("PLTR.US"),
											aprilDuring.get("PLTR.US")));
		System.out.println("\tQCOM " + info(map.get("QCOM.US"),true,
											prevDayDuring.get("QCOM.US"),
											aprilDuring.get("QCOM.US")));
		// For some reason this one doesn't work right - so skipped
		System.out.println("\tSCCO " + info(map.get("SCCO.US"),false,
											prevDayDuring.get("SCCO"),
											aprilDuring.get("SCCO")));
		System.out.println("\tAlso TSLA - Tesla");	
		System.out.println("");
		map = sortByValue(dayAfter,false);
		cnt = 0;
		System.out.println("* --------------------------------------------------- *");
		System.out.println("The actual day after time of 10% tariff announcement...");
		System.out.println("* --------------------------------------------------- *");
		System.out.println("*-- Top 10 --*");
		for (String ticker : map.keySet()) {
			Data data = map.get(ticker);
			String changePer = df.format(data.avgChangePercent());
			String volume = dfI.format(data.totalVol());
			System.out.println("\t" + ticker + ": (" + changePer + "). Volume: " + volume);
			cnt += 1;
			if (cnt > 9) break;
		}
		System.out.println("");
		System.out.println("*** Stocks mentioned in article");
		System.out.println("\tTSLA " + info(map.get("TSLA.US")));
		System.out.println("\tDJT " + info(map.get("DJT.US")));
		System.out.println("");
		System.out.println("*** Marjorie Taylor Greene purchases 04/08-04/09 -");
		System.out.println("\tADBE " + info(map.get("ADBE.US")));
		System.out.println("\tAMD " + info(map.get("AMD.US")));
		System.out.println("\tAMZN " + info(map.get("AMZN.US")));
		System.out.println("\tAAPL " + info(map.get("AAPL.US")));
		System.out.println("\tAMAT " + info(map.get("AMAT.US")));
		System.out.println("\tASML " + info(map.get("ASML.US")));
		System.out.println("\tBX " + info(map.get("BX.US")));
		System.out.println("\tCMI " + info(map.get("CMI.US")));
		System.out.println("\tDVN " + info(map.get("DVN.US")));
		System.out.println("\tFDX " + info(map.get("FDX.US")));
		System.out.println("\tJPM " + info(map.get("JPM.US")));
		System.out.println("\tLULU " + info(map.get("LULU.US")));
		System.out.println("\tMRK " + info(map.get("MRK.US")));
		System.out.println("\tNKE " + info(map.get("NKE.US")));
		System.out.println("\tNVDA " + info(map.get("NVDA.US")));
		System.out.println("\tPLTR " + info(map.get("PLTR.US")));
		System.out.println("\tQCOM " + info(map.get("QCOM.US")));
		System.out.println("\tSCCO " + info(map.get("SCCO.US")));
		System.out.println("\tAlso TSLA - Tesla");	
		System.out.println("");
		map = sortByValue(postDuring,false);
		cnt = 0;
		System.out.println("* ------------------------------------------ *");
		System.out.println("Days after during time of Truth Social post...");
		System.out.println("* ------------------------------------------ *");
		System.out.println("*-- Top 10 --*");
		for (String ticker : map.keySet()) {
			Data data = map.get(ticker);
			String changePer = df.format(data.avgChangePercent());
			String volume = dfI.format(data.totalVol());
			System.out.println("\t" + ticker + ": (" + changePer + "). Volume: " + volume);
			cnt += 1;
			if (cnt > 9) break;
		}
		System.out.println("");
		System.out.println("*** Stocks mentioned in article");
		System.out.print("\tTSLA " + info(map.get("TSLA.US")));
		System.out.println(" Average Volume " + dfI.format(map.get("TSLA.US").totalVol()/POST_APRIL_DAYS));
		System.out.print("\tDJT " + info(map.get("DJT.US")));
		System.out.println(" Average Volume " + dfI.format(map.get("DJT.US").totalVol()/POST_APRIL_DAYS));
		System.out.println("");
		System.out.println("TSLA best return % in after April days " + df.format(tslaAfterBest));
		System.out.println("TSLA best date " + tslaBestAfterDate);
		System.out.println("TSLA number of after April days better " + tslaAfterBetter);
		System.out.println("DJT best return % in after April days " + df.format(djtAfterBest));
		System.out.println("DJT best date " + djtBestAfterDate); 
		System.out.println("DJT number of after April days better " + djtAfterBetter);
		System.out.println("");
		
		System.out.println("*** Marjorie Taylor Greene purchases 04/08-04/09 -");
		System.out.println("\tADBE " + info(map.get("ADBE.US")));
		System.out.println("\tAMD " + info(map.get("AMD.US")));
		System.out.println("\tAMZN " + info(map.get("AMZN.US")));
		System.out.println("\tAAPL " + info(map.get("AAPL.US")));
		System.out.println("\tAMAT " + info(map.get("AMAT.US")));
		System.out.println("\tASML " + info(map.get("ASML.US")));
		System.out.println("\tBX " + info(map.get("BX.US")));
		System.out.println("\tCMI " + info(map.get("CMI.US")));
		System.out.println("\tDVN " + info(map.get("DVN.US")));
		System.out.println("\tFDX " + info(map.get("FDX.US")));
		System.out.println("\tJPM " + info(map.get("JPM.US")));
		System.out.println("\tLULU " + info(map.get("LULU.US")));
		System.out.println("\tMRK " + info(map.get("MRK.US")));
		System.out.println("\tNKE " + info(map.get("NKE.US")));
		System.out.println("\tNVDA " + info(map.get("NVDA.US")));
		System.out.println("\tPLTR " + info(map.get("PLTR.US")));
		System.out.println("\tQCOM " + info(map.get("QCOM.US")));
		System.out.println("\tSCCO " + info(map.get("SCCO.US")));
		System.out.println("\tAlso TSLA - Tesla");	
		System.out.println("");
		map = sortByValue(postAfter,false);
		cnt = 0;
		System.out.println("* ----------------------------------------- *");
		System.out.println("Days after time of 10% tariff announcement...");
		System.out.println("* ----------------------------------------- *");
		System.out.println("*-- Top 10 --*");
		for (String ticker : map.keySet()) {
			Data data = map.get(ticker);
			String changePer = df.format(data.avgChangePercent());
			String volume = dfI.format(data.totalVol());
			System.out.println("\t" + ticker + ": (" + changePer + "). Volume: " + volume);
			cnt += 1;
			if (cnt > 9) break;
		}
		System.out.println("");
		System.out.println("*** Stocks mentioned in article");
		System.out.println("\tTSLA " + info(map.get("TSLA.US")));
		System.out.println("\tDJT " + info(map.get("DJT.US")));
		System.out.println("");
		System.out.println("*** Marjorie Taylor Greene purchases 04/08-04/09 -");
		System.out.println("\tADBE " + info(map.get("ADBE.US")));
		System.out.println("\tAMD " + info(map.get("AMD.US")));
		System.out.println("\tAMZN " + info(map.get("AMZN.US")));
		System.out.println("\tAAPL " + info(map.get("AAPL.US")));
		System.out.println("\tAMAT " + info(map.get("AMAT.US")));
		System.out.println("\tASML " + info(map.get("ASML.US")));
		System.out.println("\tBX " + info(map.get("BX.US")));
		System.out.println("\tCMI " + info(map.get("CMI.US")));
		System.out.println("\tDVN " + info(map.get("DVN.US")));
		System.out.println("\tFDX " + info(map.get("FDX.US")));
		System.out.println("\tJPM " + info(map.get("JPM.US")));
		System.out.println("\tLULU " + info(map.get("LULU.US")));
		System.out.println("\tMRK " + info(map.get("MRK.US")));
		System.out.println("\tNKE " + info(map.get("NKE.US")));
		System.out.println("\tNVDA " + info(map.get("NVDA.US")));
		System.out.println("\tPLTR " + info(map.get("PLTR.US")));
		System.out.println("\tQCOM " + info(map.get("QCOM.US")));
		System.out.println("\tSCCO " + info(map.get("SCCO.US")));
		System.out.println("\tAlso TSLA - Tesla");	
		System.out.println("");
	}
	
	private static void doFile(Path file) throws Exception {
		String[] fields;
		try {
			List<String> data = Files.readAllLines(file,ISO_8859_1);
			for (int i = 1; i < data.size(); i++) {
				// <TICKER>,<PER>,<DATE>,<TIME>,<OPEN>,<HIGH>,<LOW>,<CLOSE>,<VOL>,<OPENINT>
				fields = data.get(i).split(",");
				// if (fields[TIME].equals("160000")) {
				int time = Integer.parseInt(fields[TIME]);
				//int hour = Integer.parseInt(fields[TIME].substring(0,2));
				//int minutes = Integer.parseInt(fields[TIME].substring(2,4));
				if (i == 1 && time != 160000) break;
				int dateInt = Integer.parseInt(fields[DATE]);
				if (dateInt == THE_DAY) {
					compareDay(fields);
				}
				else if (dateInt < THE_DAY) {
					beforeDay(fields);
				}
				else {
					afterDay(fields);
				}
			}
		}
		catch (IOException ioex) {
			ioex.printStackTrace();
		}
	}
	
	private static void compareDay(String[] fields) throws Exception {	 
		int time = Integer.parseInt(fields[TIME]);
		if (time < ANNOUNCE_TIME) {
			Data data = dayDuring.get(fields[TICKER]);
			if (data == null) {
				data = new Data(toDbl(fields[OPEN]));
			}
			data.addVol(toInt(fields[VOL]));
			data.updatePrices(toDbl(fields[OPEN]), toDbl(fields[CLOSE]));
			dayDuring.put(fields[TICKER], data);
		}
		else {
			Data data = dayAfter.get(fields[TICKER]);
			if (data == null) {
				data = new Data(toDbl(fields[OPEN]));
			}
			data.addVol(toInt(fields[VOL]));
			data.updatePrices(toDbl(fields[OPEN]), toDbl(fields[CLOSE]));
			dayAfter.put(fields[TICKER], data);
		}
	}
			
	private static void beforeDay(String[] fields) throws Exception {
		int time = Integer.parseInt(fields[TIME]);
		int date = toInt(fields[DATE]);
		if (time < ANNOUNCE_TIME) {
			if (date == PRIOR_DAY) {
				Data data = prevDayDuring.get(fields[TICKER]);
				if (data == null) {
					data = new Data(toDbl(fields[OPEN]));
				}
				data.addVol(toInt(fields[VOL]));
				data.updatePrices(toDbl(fields[OPEN]), toDbl(fields[CLOSE]));
				prevDayDuring.put(fields[TICKER], data);				
			}
			else if (date > 20250400 && date < PRIOR_DAY){     // April not counting prior 
				Data data = aprilDuring.get(fields[TICKER]);
				if (data == null) {
					data = new Data(toDbl(fields[OPEN]));
				}
				data.addVol(toInt(fields[VOL]));
				data.updatePrices(toDbl(fields[OPEN]), toDbl(fields[CLOSE]));
				aprilDuring.put(fields[TICKER], data);	
				// The following might miss last day but we already check previous day
				if (fields[TICKER].equals("TSLA.US") && date != tslaCurrentDate) {
					if (tslaCurrentData == null) {
						tslaCurrentData = new Data(toDbl(fields[OPEN]));						
						tslaCurrentData.addVol(toInt(fields[VOL]));
						tslaCurrentData.updatePrices(toDbl(fields[OPEN]), toDbl(fields[CLOSE]));
						tslaCurrentDate = toInt(fields[DATE]);
					}
					else {         // finished prior day - check it
						if (tslaCurrentData.avgChangePercent() > tslaBeforeBest) {
							tslaBeforeBest = tslaCurrentData.avgChangePercent();
							tslaBestBeforeDate = tslaCurrentDate;
						}
						if (tslaCurrentData.avgChangePercent() > TSLA_PER) {
							tslaBeforeBetter += 1;
						}	
						tslaCurrentData = null;
					}	
				}
				else if (fields[TICKER].equals("TSLA.US") && date == tslaCurrentDate) {
					tslaCurrentData.updateClose(toDbl(fields[CLOSE]));
				}
				if (fields[TICKER].equals("DJT.US") && date != djtCurrentDate) {
					if (djtCurrentData == null) {
						djtCurrentData = new Data(toDbl(fields[OPEN]));				
						djtCurrentData.addVol(toInt(fields[VOL]));
						djtCurrentData.updatePrices(toDbl(fields[OPEN]), toDbl(fields[CLOSE]));	
						djtCurrentDate = toInt(fields[DATE]);			
					}
					else {        // finished prior day - check it
						if (djtCurrentData.avgChangePercent() > djtBeforeBest) {
							djtBeforeBest = djtCurrentData.avgChangePercent();
							djtBestBeforeDate = djtCurrentDate;
						}	
						if (djtCurrentData.avgChangePercent() > DJT_PER) {
							djtBeforeBetter += 1;
						}	
						djtCurrentData = null;	
					}	
				}
				else if (fields[TICKER].equals("DJT.US") && date != djtCurrentDate) {
					djtCurrentData.updateClose(toDbl(fields[CLOSE]));
				}
			}
		}
		else {
			if (toInt(fields[DATE]) == PRIOR_DAY) {
				Data data = prevDayAfter.get(fields[TICKER]);
				if (data == null) {
					data = new Data(toDbl(fields[OPEN]));
				}
				data.addVol(toInt(fields[VOL]));
				data.updatePrices(toDbl(fields[OPEN]), toDbl(fields[CLOSE]));
				prevDayAfter.put(fields[TICKER], data);				
			}
			else if (date > 20250400 && date < PRIOR_DAY){
				Data data = aprilAfter.get(fields[TICKER]);
				if (data == null) {
					data = new Data(toDbl(fields[OPEN]));
				}
				data.addVol(toInt(fields[VOL]));
				data.updatePrices(toDbl(fields[OPEN]), toDbl(fields[CLOSE]));
				aprilAfter.put(fields[TICKER], data);				
			}		
		}
	}
	
	private static void afterDay(String[] fields) throws Exception {
		int time = Integer.parseInt(fields[TIME]);
		int date = toInt(fields[DATE]);
		if (time < ANNOUNCE_TIME) {
			Data data = postDuring.get(fields[TICKER]);
			if (data == null) {
				data = new Data(toDbl(fields[OPEN]));
			}
			data.addVol(toInt(fields[VOL]));
			data.updatePrices(toDbl(fields[OPEN]), toDbl(fields[CLOSE]));
			postDuring.put(fields[TICKER], data);
			if (fields[TICKER].equals("TSLA.US") && data.avgChangePercent() >= tslaAfterBest) {
				tslaAfterBest = data.avgChangePercent();
			}		
			if (fields[TICKER].equals("DJT.US") && data.avgChangePercent() >= djtAfterBest) {
				djtAfterBest = data.avgChangePercent();
			}	
			// The following might miss last day but we already check previous day
			if (fields[TICKER].equals("TSLA.US") && date != tslaCurrentDate) {
				if (tslaCurrentData == null) {
					tslaCurrentData = new Data(toDbl(fields[OPEN]));
					tslaCurrentData.addVol(toInt(fields[VOL]));
					tslaCurrentData.updatePrices(toDbl(fields[OPEN]), toDbl(fields[CLOSE]));
					tslaCurrentDate = date;
				}
				else {         // finished prior day - check it
					if (tslaCurrentData.avgChangePercent() > tslaAfterBest) {
						tslaAfterBest = tslaCurrentData.avgChangePercent();
						tslaBestAfterDate = tslaCurrentDate;
					}	
					if (tslaCurrentData.avgChangePercent() > TSLA_PER) {
						tslaBeforeBetter += 1;
					}	
					tslaCurrentData = null;		
				}				
			}
			else if (fields[TICKER].equals("TSLA.US") && date == tslaCurrentDate) {
				tslaCurrentData.updateClose(toDbl(fields[CLOSE]));
			}
			if (fields[TICKER].equals("DJT.US") && date != djtCurrentDate) {
				if (djtCurrentData == null) {
					djtCurrentData = new Data(toDbl(fields[OPEN]));			
					djtCurrentData.addVol(toInt(fields[VOL]));
					djtCurrentData.updatePrices(toDbl(fields[OPEN]), toDbl(fields[CLOSE]));
					djtCurrentDate = date;
				}
				else {        // finished prior day - check it
					if (djtCurrentData.avgChangePercent() > djtBeforeBest) {
						djtBeforeBest = djtCurrentData.avgChangePercent();
						djtBestAfterDate = djtCurrentDate;
					}	
					if (djtCurrentData.avgChangePercent() > DJT_PER) {
						djtBeforeBetter += 1;
					}	
					djtCurrentData = null;
				}				
			}
			else if (fields[TICKER].equals("DJT.US") && date == djtCurrentDate) {
				djtCurrentData.updateClose(toDbl(fields[CLOSE]));
			}				
		}
		else {
			Data data = postAfter.get(fields[TICKER]);
			if (data == null) {
				data = new Data(toDbl(fields[OPEN]));
			}
			data.addVol(toInt(fields[VOL]));
			data.updatePrices(toDbl(fields[OPEN]), toDbl(fields[CLOSE]));
			postAfter.put(fields[TICKER], data);							
		}
	}
	
    private static Map<String, Data> sortByValue(Map<String, Data> unsortMap, final boolean order)
    {
        List<Entry<String, Data>> list = new LinkedList<>(unsortMap.entrySet());

        // Sorting the list based on values
        list.sort((o1, o2) -> order ? o1.getValue().compareTo(o2.getValue()) == 0
                ? o1.getKey().compareTo(o2.getKey())
                : o1.getValue().compareTo(o2.getValue()) : o2.getValue().compareTo(o1.getValue()) == 0
                ? o2.getKey().compareTo(o1.getKey())
                : o2.getValue().compareTo(o1.getValue()));
        return list.stream().collect(Collectors.toMap(Entry::getKey, Entry::getValue, (a, b) -> b, LinkedHashMap::new));

    }

	private static String info(Data data) {
		return info(data, false, null, null);
	}
	
	private static String info(Data data, boolean calcVolDiff, Data prevData, Data aprilData) {
		StringBuilder sb = new StringBuilder();
		String changePer = df.format(data.avgChangePercent());
		String volume = dfI.format(data.totalVol());
		sb.append("\tPer: ").append(changePer);
		sb.append("\tTotal volume " + volume);
		if (calcVolDiff) {
			int prevDiff = data.totalVol() - prevData.totalVol();
			sb.append("\tPrev volume diff " + dfI.format(prevDiff));
			int prevAprilDiff = data.totalVol() - aprilData.totalVol() / PREV_APRIL_DAYS;
			sb.append("\tPrev Average April volume diff " + dfI.format(prevAprilDiff));
		}
		return sb.toString();	
	}
	
    private static void printMap(Map<String, Integer> map)
    {
        map.forEach((key, value) -> System.out.println("Key : " + key + " Value : " + value));
    }
	
	private static int toInt(String field) throws Exception {
		return Integer.parseInt(field);
	}
	
	private static double toDbl(String field) throws Exception {
		return Double.parseDouble(field);
	}

	private static long calcIntSum(ArrayList<Integer> list) {
		long sum = 0L;
		for (Integer num : list) {
			sum += num;
		}
		return sum;
	}
	
	private static double calcDblSum(ArrayList<Double> list) {
		double sum = 0d;
		for (Double num : list) {
			sum += num;
		}
		return sum;
	}
		
	private static double calcIntMean(ArrayList<Integer> list) {
		double sum = 0d;
		for (Integer num : list) {
			sum += num;
		}
		
		return sum / list.size();
	}
	
	private static double calcDblMean(ArrayList<Double> list) {
		double sum = 0d;
		for (Double num : list) {
			sum += num;
		}
		
		return sum / list.size();
	}
}

class Data implements Comparable<Data> {
	
	int cntVol = 0;
	int sumVol = 0;
	double open = 0d, close = 0d;
	int priceUpCnt = 0;
	int priceDownCnt = 0;
	DecimalFormat df = new DecimalFormat("#.##%");
	DecimalFormat dfI = new DecimalFormat("#,###");
	
	public Data(double open) {
		this.open = open;
	}
	
	public double avgChangePercent() {
		return (close - open) / open;
	}
	
	public int compareTo(Data other) {
		if (avgChangePercent() < other.avgChangePercent())
			return -1;
		if (avgChangePercent() > other.avgChangePercent())
			return 1;
		return 0;
  	}
  	
	public void addVol(int vol) {
		sumVol += vol;
		cntVol += 1;
	}
	 
	public void updateClose(double close) {
		if (close > open) {
			priceUpCnt += 1;
		}
		else {
			priceDownCnt += 1;
		}
		this.close = close;		
	}
	
	public void updatePrices(double open, double close) {
		if (close > open) {
			priceUpCnt += 1;
		}
		else {
			priceDownCnt += 1;
		}
		this.close = close;
	}
	
	public int averageVol() {
		return sumVol / cntVol;
	}
	
	public int totalVol() {
		return sumVol;
	}
	
	public int getCnt() {
		return priceUpCnt + priceDownCnt;
	}
	
	public int getUpCnt() {
		return priceUpCnt;
	}
	
	public int getDownCnt() {
		return priceDownCnt;
	}
	
	public String toString() {
		StringBuilder sb = new StringBuilder();
		String changePer = df.format(avgChangePercent());
		String volume = dfI.format(totalVol());
		sb.append("Price open " + open + " close " + close);
		sb.append(" (").append(changePer).append(") ");
		sb.append("total volume " + volume);
		return sb.toString();
	}
}