ics4u.ics4u_final_project.Database.java Source code

Java tutorial

Introduction

Here is the source code for ics4u.ics4u_final_project.Database.java

Source

/* Isaac Wismer
 *  Jun 15, 2015
 * This class contains code to be able to import and process recipes
 */
/*
Copyright (C) 2016 Isaac Wismer & Andrew Xu
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.
    
You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package ics4u.ics4u_final_project;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.support.v4.content.ContextCompat;
import android.widget.Toast;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

/**
 * @author isaac
 */
public class Database {

    static final DecimalFormat oneDecimal = new DecimalFormat("#,##0.0");
    static final String delimiter = "#";
    static ArrayList<Object[]> fdName = new ArrayList<>(), msName = new ArrayList<>(), ntName = new ArrayList<>(),
            convFact = new ArrayList<>(), ntAmt = new ArrayList<>();
    static Recipe recipe = new Recipe();

    /**
     * Imports the data stored in files to arraylists to faster searching
     */
    public static void importData(Context c) {
        System.out.println("food Name");
        //get the file's content as an arraylist
        ArrayList<String> file = readFile(c.getResources().openRawResource(R.raw.food_nm));
        //count the number of fields
        int fields = getFields(file.get(0));
        //create arrays for each line
        String[] line = new String[fields];
        Object[] temp = new Object[fields];
        //get the number of lines
        int fileSize = file.size();
        for (int i = 0; i < fileSize; i++) {
            String s = file.get(i);
            for (int j = 0; j < fields - 1; j++) {//go through each of the fields in the line
                line[j] = s.substring(0, s.indexOf(delimiter));//add the field
                s = s.substring(s.indexOf(delimiter) + 1);//remove it from the string
            }
            //add the last field to the array
            line[fields - 1] = s;
            //add the strings to the object array
            temp[0] = Integer.parseInt(line[0]);
            temp[1] = line[1];
            //add the to the arraylist of the file
            fdName.add(temp.clone());
        }
        //repeat for each data file
        System.out.println("Conv Fac");
        file = readFile(c.getResources().openRawResource(R.raw.conv_fac));
        fields = getFields(file.get(0));
        line = new String[fields];
        temp = new Object[fields];
        for (int i = 0; i < file.size(); i++) {
            String s = file.get(i);
            for (int j = 0; j < fields - 1; j++) {//go through each of the fields in the line
                line[j] = s.substring(0, s.indexOf(delimiter));//add the field
                s = s.substring(s.indexOf(delimiter) + 1);//remove it from the string
            }
            line[fields - 1] = s;
            if (line[2].equals("")) {
                continue;
            }
            temp[0] = Integer.parseInt(line[0]);
            temp[1] = Integer.parseInt(line[1]);
            temp[2] = Double.parseDouble(line[2]);
            convFact.add(temp.clone());
        }
        System.out.println("Nt amount");
        file = readFile(c.getResources().openRawResource(R.raw.nt_amt));
        fields = getFields(file.get(0));
        line = new String[fields];
        temp = new Object[fields];
        for (int i = 0; i < file.size(); i++) {
            String s = file.get(i);
            for (int j = 0; j < fields - 1; j++) {//go through each of the fields in the line
                line[j] = s.substring(0, s.indexOf(delimiter));//add the field
                s = s.substring(s.indexOf(delimiter) + 1);//remove it from the string
            }
            line[fields - 1] = s;
            if (line[2].equals("")) {
                continue;
            }
            temp[0] = Integer.parseInt(line[0]);
            temp[1] = Integer.parseInt(line[1]);
            temp[2] = Double.parseDouble(line[2]);
            ntAmt.add(temp.clone());
        }
        System.out.println("measures");
        file = readFile(c.getResources().openRawResource(R.raw.measure));
        fields = getFields(file.get(0));
        line = new String[fields];
        temp = new Object[fields];
        for (int i = 0; i < file.size(); i++) {
            String s = file.get(i);
            for (int j = 0; j < fields - 1; j++) {//go through each of the fields in the line
                line[j] = s.substring(0, s.indexOf(delimiter));//add the field
                s = s.substring(s.indexOf(delimiter) + 1);//remove it from the string
            }
            line[fields - 1] = s;
            temp[0] = Integer.parseInt(line[0]);
            temp[1] = line[1];
            msName.add(temp.clone());
        }
        System.out.println("Nt name");
        file = readFile(c.getResources().openRawResource(R.raw.nt_nm));
        fields = getFields(file.get(0));
        line = new String[fields];
        temp = new Object[fields];
        for (int i = 0; i < file.size(); i++) {
            String s = file.get(i);
            for (int j = 0; j < fields - 1; j++) {//go through each of the fields in the line
                line[j] = s.substring(0, s.indexOf(delimiter));//add the field
                s = s.substring(s.indexOf(delimiter) + 1);//remove it from the string
            }
            line[fields - 1] = s;
            temp[0] = Integer.parseInt(line[0]);
            temp[1] = line[1];
            temp[2] = line[2];
            ntName.add(temp.clone());
        }
    }

    /**
     * Reads a data file to an arraylist
     *
     * @param filePath the path of the file to be read
     * @return the file as an ArrayList<String>
     */
    public static ArrayList<String> readFile(InputStream filePath) {
        //create a buffered reader
        BufferedReader br = new BufferedReader(new InputStreamReader(filePath));
        //create an arraylist for the file
        ArrayList<String> file = new ArrayList<>();
        try {
            //read each line of the file and add it to the arraylist
            String s = br.readLine();
            while (s != null) {
                file.add(s);
                s = br.readLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("finish read");

        return file;
    }

    /**
     * returns the number of fields for the given string
     *
     * @param s the string to test
     * @return the number of fields
     */
    public static int getFields(String s) {
        int fields = 1;
        //minimum of one field
        //count the number of additional fields
        for (int i = 0; i < s.length(); i++) {
            if (s.substring(i, i + 1).equals(delimiter)) {
                fields++;
            }
        }
        return fields;
    }

    /**
     * Searches the list of ingredients for the keyword
     *
     * @param keyword the word(s) to search with
     * @return a list of the matches
     */
    public static ArrayList<Ingredient> search(String keyword) {
        keyword = keyword.toUpperCase();
        //create new arraylist for the matched
        ArrayList<Ingredient> match = new ArrayList<>(0);
        int index;
        //create new arraylist for the search queryies
        ArrayList<String> query = new ArrayList<>(0);
        //separate the search string into queryies
        while (keyword.contains(",")) {
            index = keyword.indexOf(",");
            query.add(keyword.substring(0, index));
            keyword = keyword.substring(index + 1);
            if (keyword.substring(0, 1).equals(" ")) {
                keyword = keyword.substring(1);
            }
        }
        //add the remaining part of the string to the queries
        query.add(keyword);
        //read from the nutrients to check if they match the queries
        //read from the file
        //read each line and check if it matched the search terms
        int length = fdName.size();
        for (int i = 0; i < length; i++) {
            //System.out.println(fdName.get(i)[1]);
            boolean matches = true;
            //check if the food item matches the query
            for (int j = 0; j < query.size(); j++) {
                if (!(fdName.get(i)[1]).toString().contains(query.get(j))) {
                    matches = false;
                }
            }
            //if it does add it to the list of matches
            if (matches) {
                match.add(new Ingredient((Integer) fdName.get(i)[0], (String) fdName.get(i)[1]));
            }
        }
        return match;
    }//End searchByName()

    /**
     * This method opens a saved recipe and re-assings the variable with the new
     * data
     *
     * @param file The file path
     * @return the recipe that was opened
     */
    public static Recipe open(InputStream file) {
        System.out.println(file);
        Recipe opened = new Recipe();
        try {
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(file, "UTF-8");

            doc.getDocumentElement().normalize();
            //title
            NodeList nList = doc.getElementsByTagName("title");
            Node nNode = nList.item(0);
            Element eElement = (Element) nNode;
            opened.setTitle(eElement.getTextContent());
            System.out.println(opened.getTitle());
            //instructions
            nList = doc.getElementsByTagName("instructions");
            nNode = nList.item(0);
            eElement = (Element) nNode;
            opened.setInstructions(eElement.getTextContent());
            //Servings
            nList = doc.getElementsByTagName("servings");
            nNode = nList.item(0);
            eElement = (Element) nNode;
            if (eElement.getTextContent().equals("")) {
                opened.setServings(1);
            } else {
                opened.setServings(Integer.parseInt(eElement.getTextContent()));
            }
            //Serving Name
            nList = doc.getElementsByTagName("servingName");
            nNode = nList.item(0);
            eElement = (Element) nNode;
            opened.setServingName(eElement.getTextContent());
            //photo
            nList = doc.getElementsByTagName("photo");
            nNode = nList.item(0);
            eElement = (Element) nNode;
            if (eElement.getTextContent().equals("")) {
                opened.setPhoto(-1);
            } else {
                opened.setPhoto(Integer.parseInt(eElement.getTextContent()));
            }
            //ingredients
            nList = doc.getElementsByTagName("ingredients");
            for (int temp = 0; temp < nList.getLength(); temp++) {
                nNode = nList.item(temp);
                if (nNode.getNodeType() == Node.ELEMENT_NODE) {

                    eElement = (Element) nNode;
                    Ingredient i = new Ingredient();
                    i.setID(Integer.parseInt(eElement.getElementsByTagName("ID").item(0).getTextContent()));
                    i.setName(eElement.getElementsByTagName("name").item(0).getTextContent());
                    i.setFormattedName(eElement.getElementsByTagName("formattedName").item(0).getTextContent());
                    i.setUnit(eElement.getElementsByTagName("unitName").item(0).getTextContent());
                    i.setUnitNum(
                            Integer.parseInt(eElement.getElementsByTagName("unitNum").item(0).getTextContent()));
                    i.setFractionName(eElement.getElementsByTagName("fractionName").item(0).getTextContent());
                    i.setFractionNum(Integer
                            .parseInt(eElement.getElementsByTagName("fractionNum").item(0).getTextContent()));
                    i.setQuantity(
                            Integer.parseInt(eElement.getElementsByTagName("quantity").item(0).getTextContent()));

                    //measures
                    NodeList measureList = eElement.getElementsByTagName("measures");
                    for (int j = 0; j < measureList.getLength(); j++) {
                        Node mNode = measureList.item(j);
                        if (nNode.getNodeType() == Node.ELEMENT_NODE) {
                            Element mElement = (Element) nNode;
                            Measures m = new Measures();
                            m.setID(Integer.parseInt(mElement.getElementsByTagName("id").item(j).getTextContent()));
                            m.setConversion(Double.parseDouble(
                                    mElement.getElementsByTagName("conversion").item(j).getTextContent()));
                            m.setName(mElement.getElementsByTagName("measureName").item(j).getTextContent());
                            i.addMeasureFull(m);
                        }
                    }
                    opened.addIngredient(i);
                }
            }
            for (int i = 0; i < opened.getIngredients().size(); i++) {
                opened.addListItem(opened.getSingleIngredientIndex(i).getFormattedName());
            }

        } catch (ParserConfigurationException | SAXException | IOException | DOMException e) {
            System.out.println("File Read Error: " + e.toString());
        }
        return opened;
    }//end open()

    /**
     * This method creates the output that will be displayed for the user
     * This method is not used ever right now
     *
     * @param recipe          The entire recipe with all ingredient and measure
     *                        information
     * @param recipeNutrients the nutrients of the recipe
     * @param label           whether or not to print the information as a label
     * @return a string with the formatted output
     */
    public static String createOutput(Recipe recipe, Double[] recipeNutrients, boolean label) {
        String output;
        //make the title
        output = "Nutrition Facts for " + recipe.getTitle() + "\r\n\r\n";
        output += "Ingredients:\r\n";
        //print out the ingredients
        for (int i = 0; i < recipe.getList().size(); i++) {
            output += recipe.getList().get(i) + "\r\n";
        }
        output += "\r\n\r\n";
        //print out the instructions
        if (!recipe.getInstructions().equals("")) {
            output += "Directions\n";
            output += recipe.getInstructions();
            output += "\r\n\r\n";
        }
        if (!label) {//print out the info if its not a label
            for (int i = 0; i < ntName.size(); i++) {
                int id = (int) ntName.get(i)[0];
                //makes sure there is data for the nutrient
                if (recipeNutrients[id] != null) {
                    //makes sure the value is not 0
                    if (!oneDecimal.format((recipeNutrients[id])).equals("0.0")) {
                        //add the nutrient name
                        output += ntName.get(i)[2];
                        //add the periods to line up the output
                        int dots = (80 - ntName.get(i)[2].toString().length());
                        for (int j = 0; j < dots; j++) {
                            output += ".";
                        }
                        //add the nutrient information
                        output += oneDecimal.format((recipeNutrients[id])) + ntName.get(i)[1] + "\r\n";
                    }
                }
            }
        } else {//if it is a label
            //make the percent decimal format
            DecimalFormat onePer = new DecimalFormat("#,##0%");
            //begin printing out the label
            output += "Makes " + recipe.getServings() + ". The label is made for that serving size.\r\n";
            output += "=========================================\r\n";
            output += "|Nutrition Facts\t\t\t|\r\n";
            output += "|Per " + recipe.getServingName();
            double servingsD = recipe.getServings();
            //the if staments checks the size of the number to determine the 
            //number of tabs that are necissary to line up the label
            if (recipe.getServingName().length() < 5) {
                output += "\t\t\t\t";
            } else if (recipe.getServingName().length() >= 30) {
            } else if (recipe.getServingName().length() >= 22) {
                output += "\t";
            } else if (recipe.getServingName().length() >= 14) {
                output += "\t\t";
            } else {
                output += "\t\t\t";
            }
            output += "|\r\n";
            output += "|=======================================|\r\n";
            output += "|Amount\t\t\t% Daily Value\t|\r\n";
            output += "|Teneur\t\t % valeur quotodoenne\t|\r\n";
            output += "|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|\r\n";
            output += "|Calories/Calories " + (int) (recipeNutrients[208] / servingsD) + "\t\t";
            if ((recipeNutrients[208] / servingsD) < 10000) {
                output += "\t";
            }
            output += "|\r\n";
            output += "|---------------------------------------|\r\n";
            output += "|Fat/Lipides " + (int) (recipeNutrients[204] / servingsD) + "g\t\t";
            if ((int) (recipeNutrients[204] / servingsD) <= 9) {
                output += "\t";
            }
            output += onePer.format((recipeNutrients[204] / servingsD) / 60.0) + "\t|\r\n";
            output += "|---------------------------------------|\r\n";
            output += "|\tSaturated/Satures " + (int) (recipeNutrients[606] / servingsD) + "g\t"
                    + onePer.format((recipeNutrients[606] / servingsD) / 20.0) + "\t|\r\n";
            output += "|\t+ Trans/trans " + (int) (recipeNutrients[605] / servingsD) + "g\t\t|\r\n";
            output += "|---------------------------------------|\r\n";
            output += "|Cholesterol/Cholesterol " + (int) (recipeNutrients[601] / servingsD) + "mg\t";
            if (recipeNutrients[601] / servingsD < 1000) {
                output += "\t";
            }
            output += "|\r\n";
            output += "|---------------------------------------|\r\n";
            output += "|Sodium/Sodium " + (int) (recipeNutrients[307] / servingsD) + "mg\t\t"
                    + onePer.format((recipeNutrients[307] / servingsD) / 2400.0) + "\t|\r\n";
            output += "|---------------------------------------|\r\n";
            output += "|Carbohydrate/Glucides " + (int) (recipeNutrients[205] / servingsD) + "g\t"
                    + onePer.format((recipeNutrients[205] / servingsD) / 300.0) + "\t|\r\n";
            output += "|---------------------------------------|\r\n";
            output += "|\tFibre/Fibres " + (int) (recipeNutrients[291] / servingsD) + "g\t";
            if ((recipeNutrients[291] / servingsD) < 10) {
                output += "\t";
            }
            output += onePer.format((recipeNutrients[291] / servingsD) / 25.0) + "\t|\r\n";
            output += "|\t--------------------------------|\r\n";
            output += "|\tSugars/Sucres " + (int) (recipeNutrients[269] / servingsD) + "g\t\t|\r\n";
            output += "|---------------------------------------|\r\n";
            output += "|Protein/Proteines " + (int) (recipeNutrients[203] / servingsD) + "g\t\t";
            if (recipeNutrients[203] / servingsD < 1000) {
                output += "\t";
            }
            output += "|\r\n";
            output += "|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|\r\n";
            output += "|Vitamin A/Vitamine A\t\t**%\t|\r\n";
            output += "|---------------------------------------|\r\n";
            output += "|Vitamin C/Vitamine C\t\t" + onePer.format((recipeNutrients[401] / servingsD) / 60.0)
                    + "\t|\r\n";
            output += "|---------------------------------------|\r\n";
            output += "|Calcium/Calcium\t\t" + onePer.format((recipeNutrients[301] / servingsD) / 1100.0)
                    + "\t|\r\n";
            output += "|---------------------------------------|\r\n";
            output += "|Iron/fer\t\t\t" + onePer.format((recipeNutrients[303] / servingsD) / 14.0) + "\t|\r\n";
            output += "=========================================\r\n";
        }
        return output;
    }//End createOutput()

    /**
     * This method gets the information for each ingredient needed to create the
     * label/output
     *
     * @param recipe The complete recipe with all the ingredient and measure
     *               info
     * @param label  a boolean stating whether or not to print as a label
     * @param pdf    Whether or not the output is being used to print a pdf
     * @return a string with the output
     */
    public static String recipe(Recipe recipe, boolean label, boolean pdf) {
        Double[] recipeNutrients = new Double[870], indiviual;
        double nutrientConv = 1.0, portionSize = 100.0;
        for (int i = 0; i < recipeNutrients.length; i++) {
            recipeNutrients[i] = 0.0;
        }
        for (int i = 0; i < recipe.size(); i++) {
            //get the nutrient data for the food
            indiviual = getNutrientData(recipe.getSingleIngredientIndex(i).getID());
            System.out.println("Ingredient: " + recipe.getSingleIngredientIndex(i).getName());
            System.out.println("Measurement: " + recipe.getSingleIngredientIndex(i).getFractionName());
            //convert the nutrients to be for the specified quantity
            if (recipe.getSingleIngredientIndex(i).getUnit().equals("g")) {
                //grams just have to be divided by 100 to get the conversion rate
                nutrientConv = ((double) recipe.getSingleIngredientIndex(i).getQuantity()) / 100.0;
            } else if (recipe.getSingleIngredientIndex(i).getUnit().equals("Metric Cooking Measures")) {
                //get the correct portion size (measurement)
                int fractionNum = recipe.getSingleIngredientIndex(i).getFractionNum();
                switch (fractionNum) {
                case 0:
                    portionSize = 1.25;
                    break;
                case 1:
                    portionSize = 2.5;
                    break;
                case 2:
                    portionSize = 5.0;
                    break;
                case 3:
                    portionSize = 15.0;
                    break;
                case 4:
                    portionSize = 62.5;
                    break;
                case 5:
                    portionSize = 250.0 / 3.0;
                    break;
                case 6:
                    portionSize = 125;
                    break;
                default:
                    portionSize = 250.0;
                    break;
                }
                //multiply the measure by the specified quantity
                portionSize *= (double) recipe.getSingleIngredientIndex(i).getQuantity();
                System.out.println("Portion Size = " + portionSize + "mL");
            } else if (recipe.getSingleIngredientIndex(i).getUnit().equals("Other")) {
                //look for the matching portion size
                for (int j = 0; j < recipe.getSingleIngredientIndex(i).getMeasures().size(); j++) {
                    if (recipe.getSingleIngredientIndex(i).getFractionName()
                            .equals(recipe.getSingleIngredientIndex(i).getSingleMeasureIndex(j).getName())) {
                        nutrientConv = recipe.getSingleIngredientIndex(i).getSingleMeasureIndex(j).getConversion()
                                * recipe.getSingleIngredientIndex(i).getQuantity();
                        j = recipe.getSingleIngredientIndex(i).getMeasures().size() + 1;
                    }
                }
            }
            //set the conversion based on the available measures
            if (recipe.getSingleIngredientIndex(i).getUnit().equals("Metric Cooking Measures")
                    || recipe.getSingleIngredientIndex(i).getUnit().equals("mL")) {
                for (int j = 0; j < recipe.getSingleIngredientIndex(i).getMeasures().size(); j++) {
                    int ID = recipe.getSingleIngredientIndex(i).getSingleMeasureIndex(j).getID();
                    double conversion = recipe.getSingleIngredientIndex(i).getSingleMeasureIndex(j).getConversion();
                    if (ID > 340 && ID < 380) {
                        nutrientConv = portionSize * (conversion / 100.0);
                        break;
                    } else if (ID == 383) {
                        nutrientConv = portionSize * (conversion / 125.0);
                        break;
                    } else if (ID == 415 || ID == 418 || ID == 939 || ID == 943) {
                        nutrientConv = portionSize * (conversion / 250.0);
                        break;
                    } else if (ID == 439) {
                        nutrientConv = portionSize * (conversion / 5.0);
                        break;
                    } else if (ID == 413) {
                        nutrientConv = portionSize * (conversion / 200.0);
                        break;
                    } else if (ID == 414) {
                        nutrientConv = portionSize * (conversion / 225.0);
                        break;
                    } else if (ID == 419) {
                        nutrientConv = portionSize * (conversion / 275.0);
                        break;
                    } else if (ID == 428) {
                        nutrientConv = portionSize * (conversion / 30.0);
                        break;
                    } else if (ID == 429) {
                        nutrientConv = portionSize * (conversion / 300.0);
                        break;
                    } else if (ID == 430) {
                        nutrientConv = portionSize * (conversion / 375.0);
                        break;
                    } else if (ID >= 385 && ID <= 387) {
                        nutrientConv = portionSize * (conversion / 15.0);
                        break;
                    } else if (ID == 388) {
                        nutrientConv = portionSize * (conversion / 150.0);
                        break;
                    } else if (ID == 389) {
                        nutrientConv = portionSize * (conversion / 175.0);
                        break;
                    } else if (ID == 638) {
                        nutrientConv = portionSize * (conversion / 50.0);
                        break;
                    } else if (ID == 640) {
                        nutrientConv = portionSize * (conversion / 60.0);
                        break;
                    } else if (ID == 641) {
                        nutrientConv = portionSize * (conversion / 75.0);
                        break;
                    } else if (ID == 923) {
                        nutrientConv = portionSize * (conversion / 45.0);
                        break;
                    } else if (ID == 932) {
                        nutrientConv = portionSize * (conversion / 80.0);
                        break;
                    }
                }
            }
            System.out.println("Conversion Rate = " + nutrientConv + "\n End of Ingredient\n");
            //add the individual nutrients to the recipe ingredients
            for (int j = 0; j < 870; j++) {
                if (indiviual[j] != null) {
                    recipeNutrients[j] += (indiviual[j] * nutrientConv);
                }
            }
        }
        if (pdf) {
            recipe.setNutrients(recipeNutrients.clone());
            return null;
        }
        //ask for the name of the recipe
        if (recipe.getTitle().equals("")) {
            //recipe.setTitle(JOptionPane.showInputDialog("Please enter the name of the recipe"));
        }
        return createOutput(recipe, recipeNutrients, label);
    }//End recipe()

    /**
     * This method collects all the nutrient amounts
     *
     * @param ID the food ID of the food item
     * @return an array with the nutrient ID and the amount of that nutrient
     */
    public static Double[] getNutrientData(int ID) {
        Double[] nutrients = new Double[870];
        int begin = binarySearch(ntAmt, ID, 0, ntAmt.size() - 1);
        if (begin == -1) {
            System.out.println("Not Found");
        }
        //step back to the beginning of the nutrient
        while (begin > 0 && (int) ntAmt.get(begin - 1)[0] == ID) {
            begin--;
        }
        //read until the end of the nutrient
        for (int i = begin; (int) ntAmt.get(i)[0] == ID; i++) {
            nutrients[(int) ntAmt.get(i)[1]] = (double) ntAmt.get(i)[2];
        }
        return nutrients;
    }//End getData()

    /**
     * Imports the recipes from the recipe folder
     *
     * @return an array list containing all the recipes in the folder
     */
    public static ArrayList<Recipe> importRecipes(Context c) {
        //create a list of the recipes
        ArrayList<Recipe> database = new ArrayList<>();
        //the action changes depending on if its the first run or not
        if (MainActivity.prefs.getBoolean("firstrun", true)) {
            //set it to not being the first run anymore
            MainActivity.prefs.edit().putBoolean("firstrun", false).commit();
            //add the provided recipe(s)
            database.add(open(c.getResources().openRawResource(R.raw.banana_lentil_muffins)));
            database.add(open(c.getResources().openRawResource(R.raw.cheddar_lentil_crispies)));
            //create the recipes folder in the data folder
            File recipeFolder = new File(c.getFilesDir() + "/recipes/");
            recipeFolder.mkdir();
            //create the folder for the PDFs, if it's not already created
            File pdfFolder = new File("/sdcard/Recipes/");
            int permissionCheck = ContextCompat.checkSelfPermission(c, Manifest.permission.WRITE_EXTERNAL_STORAGE);
            if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
                if (!pdfFolder.isDirectory()) {
                    pdfFolder.mkdir();
                }
            } else {
                Toast.makeText(c, "Permission denied. Please grant storage permissions", Toast.LENGTH_LONG).show();
            }
            //save each of the imported recipes
            try {
                database.get(0).save(new File(c.getFilesDir() + "/recipes/" + 0 + ".xml"));
                database.get(1).save(new File(c.getFilesDir() + "/recipes/" + 1 + ".xml"));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        } else {
            //get a list of the files in the recipes folder
            File folder = new File(c.getFilesDir() + "/recipes/");
            File[] listOfFiles = folder.listFiles();
            //import each of the recipes
            for (File file : listOfFiles) {
                if (file.isFile() && file.getName().substring(file.getName().indexOf(".")).equals(".xml")) {
                    try {
                        database.add(open(new FileInputStream(file)));
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return database;
    }

    /**
     * binary searches an array list for the specified ID
     *
     * @param list   the list to search
     * @param id     the ID to look for
     * @param bottom the bottom index of the search area
     * @param top    the top index of the search area
     * @return the index where the ID can be found
     */
    public static int binarySearch(ArrayList<Object[]> list, int id, int bottom, int top) {
        if (top < bottom) {
            return -1;
        }
        int middle = (top + bottom) / 2;
        if (id < (Integer) list.get(middle)[0]) {
            return binarySearch(list, id, bottom, middle - 1);
        } else if (id > (Integer) list.get(middle)[0]) {
            return binarySearch(list, id, middle + 1, top);
        } else {
            return middle;
        }
    }
}