import java.awt.Color;
import java.io.*;

import smile.*;

public class Inference {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		infereceWithBayesianNetwork();
	}

	public static void infereceWithBayesianNetwork() {
		try {
			Network net = new Network();
			net.readFile("network.xdsl");
			
			try {
				BufferedReader br = new BufferedReader
					     (new InputStreamReader(new FileInputStream("observed.csv"), "UTF-8"));
				String observeLine = br.readLine();
				String[] words = observeLine.split(",");
				String nodeId = words[0];
				String value = words[1];
				net.setEvidence(nodeId, value);
				br.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			net.updateBeliefs();
			double[] values = net.getNodeValue("grade");
			String[] ids = net.getOutcomeIds("grade"); 
			
			
			try {
				FileWriter fw = new FileWriter("query.json");
				BufferedWriter bw = new BufferedWriter(fw);
				bw.write("{\n");
				bw.write("\"grade\":{\n");
				for (int i = 0; i < ids.length; i++) {
					String id = ids[i];
					double value = values[i];
					bw.write("\"" + id +"\":" + value + "");
					if (i + 1 != ids.length) {
						bw.write(",");
					}
					bw.write("\n");
				}
				bw.write("}\n");
				bw.write("}");
				bw.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			
			/*for (outcomeIndex = 0;
			 * outcomeIndex < aSuccessOutcomeIds.length; outcomeIndex++) if
			 * ("Failure".equals(aSuccessOutcomeIds[outcomeIndex])) break;
			 * 
			 * // Getting the value of the probability: aValues =
			 * net.getNodeValue("Success"); double P_SuccIsSuccGivenForeIsPoor =
			 * aValues[outcomeIndex];
			 * 
			 * System.out.println(
			 * "P(\"Success\" = Success | \"Forecast\" = Poor) = " +
			 * P_SuccIsSuccGivenForeIsPoor);*/
			
			/*
			 * // ---- We want to compute P("Forecast" = Moderate) ---- //
			 * Updating the network: net.updateBeliefs();
			 * 
			 * // Getting the handle of the node "Forecast":
			 * net.getNode("Forecast");
			 * 
			 * // Getting the index of the "Moderate" outcome: String[]
			 * aForecastOutcomeIds = net.getOutcomeIds("Forecast"); int
			 * outcomeIndex; for (outcomeIndex = 0; outcomeIndex <
			 * aForecastOutcomeIds.length; outcomeIndex++) if
			 * ("Moderate".equals(aForecastOutcomeIds[outcomeIndex])) break;
			 * 
			 * // Getting the value of the probability: double[] aValues =
			 * net.getNodeValue("Forecast"); double P_ForecastIsModerate =
			 * aValues[outcomeIndex];
			 * 
			 * System.out.println("P(\"Forecast\" = Moderate) = " +
			 * P_ForecastIsModerate);
			 * 
			 * 
			 * // ---- We want to compute P("Success" = Failure | "Forecast" =
			 * Good) ---- // Introducing the evidence in node "Forecast":
			 * net.setEvidence("Forecast", "Good");
			 * 
			 * // Updating the network: net.updateBeliefs();
			 * 
			 * // Getting the handle of the node "Success":
			 * net.getNode("Success");
			 * 
			 * // Getting the index of the "Failure" outcome: String[]
			 * aSuccessOutcomeIds = net.getOutcomeIds("Success"); for
			 * (outcomeIndex = 0; outcomeIndex < aSuccessOutcomeIds.length;
			 * outcomeIndex++) if
			 * ("Failure".equals(aSuccessOutcomeIds[outcomeIndex])) break;
			 * 
			 * // Getting the value of the probability: aValues =
			 * net.getNodeValue("Success"); double P_SuccIsFailGivenForeIsGood =
			 * aValues[outcomeIndex];
			 * 
			 * System.out.println(
			 * "P(\"Success\" = Failure | \"Forecast\" = Good) = " +
			 * P_SuccIsFailGivenForeIsGood);
			 * 
			 * // ---- We want to compute P("Success" = Success | "Forecast" =
			 * Poor) ---- // Clearing the evidence in node "Forecast":
			 * net.clearEvidence("Forecast");
			 * 
			 * // Introducing the evidence in node "Forecast":
			 * net.setEvidence("Forecast", "Good");
			 * 
			 * // Updating the network: net.updateBeliefs();
			 * 
			 * // Getting the index of the "Failure" outcome: aSuccessOutcomeIds
			 * = net.getOutcomeIds("Success"); for (outcomeIndex = 0;
			 * outcomeIndex < aSuccessOutcomeIds.length; outcomeIndex++) if
			 * ("Failure".equals(aSuccessOutcomeIds[outcomeIndex])) break;
			 * 
			 * // Getting the value of the probability: aValues =
			 * net.getNodeValue("Success"); double P_SuccIsSuccGivenForeIsPoor =
			 * aValues[outcomeIndex];
			 * 
			 * System.out.println(
			 * "P(\"Success\" = Success | \"Forecast\" = Poor) = " +
			 * P_SuccIsSuccGivenForeIsPoor);
			 */
		} catch (SMILEException e) {
			System.out.println(e.getMessage());
		}
	}

	public static void createNetwork() {
		try {
			Network net = new Network();

			// Creating node "Success" and setting/adding outcomes:
			net.addNode(Network.NodeType.Cpt, "Success");
			net.setOutcomeId("Success", 0, "Success");
			net.setOutcomeId("Success", 1, "Failure");

			// Creating node "Forecast" and setting/adding outcomes:
			net.addNode(Network.NodeType.Cpt, "Forecast");
			net.addOutcome("Forecast", "Good");
			net.addOutcome("Forecast", "Moderate");
			net.addOutcome("Forecast", "Poor");
			net.deleteOutcome("Forecast", 0);
			net.deleteOutcome("Forecast", 0);

			// Adding an arc from "Success" to "Forecast":
			net.addArc("Success", "Forecast");

			// Filling in the conditional distribution for node "Success". The
			// probabilities are:
			// P("Success" = Success) = 0.2
			// P("Success" = Failure) = 0.8
			double[] aSuccessDef = { 0.2, 0.8 };
			net.setNodeDefinition("Success", aSuccessDef);

			// Filling in the conditional distribution for node "Forecast". The
			// probabilities are:
			// P("Forecast" = Good | "Success" = Success) = 0.4
			// P("Forecast" = Moderate | "Success" = Success) = 0.4
			// P("Forecast" = Poor | "Success" = Success) = 0.2
			// P("Forecast" = Good | "Success" = Failure) = 0.1
			// P("Forecast" = Moderate | "Success" = Failure) = 0.3
			// P("Forecast" = Poor | "Success" = Failure) = 0.6
			double[] aForecastDef = { 0.4, 0.4, 0.2, 0.1, 0.3, 0.6 };
			net.setNodeDefinition("Forecast", aForecastDef);
			net.setEvidence("Forecast", "Good");
			// Writting the network to a file:
			net.writeFile("tutorial_a.xdsl");
		} catch (SMILEException e) {
			System.out.println(e.getMessage());
		}
	}

}
