def get_nuts_from_db():
    con = sql.connect(database.resource_path('spartan.db'))
    cur = con.cursor()
    sql_stmt = ('SELECT * ' 'FROM nuts ' 'ORDER BY rowid ')

    cur.execute(sql_stmt)
    nuts = cur.fetchall()

    macro_end = vit_start = len(req.macro_names)
    vit_end = mineral_start = len(req.vit_names) + len(req.mineral_names)

    macro = [
        Nutrient(name=n[0], min=n[1], max=n[2], target=n[3])
        for n in nuts[0:macro_end]
    ]
    vit = [
        Nutrient(name=n[0], min=n[1], max=n[2], target=n[3])
        for n in nuts[vit_start:vit_end]
    ]
    mineral = [
        Nutrient(name=n[0], min=n[1], max=n[2], target=n[3])
        for n in nuts[mineral_start:]
    ]

    return macro, vit, mineral
    def get_selectable_units(self):
        con = sql.connect(database.resource_path('sr_legacy/sr_legacy.db'))
        cur = con.cursor()
        sql_stmnt = ('SELECT amount, description, gm_weight '
                     'FROM weight '
                     'WHERE food_id = ?'
                     'ORDER BY sequence_num')
        cur.execute(sql_stmnt, [self.food_id])
        units = cur.fetchall()

        con.commit()
        cur.close()

        selectable_units = ['g', 'oz (28.35 g)', 'lb (453.6 g)']
        for unit in units:
            # Strip amount prefix if it's 1.0
            if unit[0] == 1.0:
                amount_display = ''
            else:
                amount_display = '{:f}'.format(
                    unit[0]).rstrip('0').rstrip('.') + ' '
            # Make unit text description with equivalent grams
            description = unit[1]
            gm_weight_display = '{:f}'.format(unit[2]).rstrip('0').rstrip('.')
            gm_weight_display = ' (' + gm_weight_display + ' g)'
            unit = amount_display + description + gm_weight_display
            # Add to selectable units if unique
            if unit not in selectable_units:
                selectable_units.append(amount_display + description +
                                        gm_weight_display)

        return selectable_units
def create_spartan_db():
    if os.path.isfile(database.resource_path('spartan.db')):
        return

    con = sql.connect(database.resource_path('spartan.db'))
    cur = con.cursor()

    person_stmt = (
        'CREATE TABLE person ( '
        'sex     TEXT, '
        'bd_year INTEGER,'
        'bd_mon  INTEGER,'
        'bd_day  INTEGER)'
    )

    nuts_stmt = (
        'CREATE TABLE nuts ( '
        'name        TEXT, '
        'min         REAL, '
        'max         REAL, '
        'target      REAL )'
    )

    foods_stmt = (
        'CREATE TABLE foods ( '
        'food_id            INTEGER, '
        'name	            TEXT, '
        'price	            REAL, '
        'price_quantity	    REAL, '
        'price_unit 	    TEXT, '
        'min	            REAL, '
        'min_unit 	        TEXT, '
        'max	            REAL, '
        'max_unit 	        TEXT, '
        'target	            REAL, '
        'target_unit 	    TEXT, '
        'nut_quantity       REAL, '
        'nut_quantity_unit  REAL )'
    )

    cur.execute(person_stmt)
    cur.execute(nuts_stmt)
    cur.execute(foods_stmt)
    insert_nuts()
    insert_default_person()
    con.commit()
    con.close()
def get_sex_bd_from_db():
    con = sql.connect(database.resource_path('spartan.db'))
    cur = con.cursor()
    sql_stmt = ('SELECT * ' 'FROM person ' 'ORDER BY rowid ')

    cur.execute(sql_stmt)
    (sex, bd_year, bd_mon, bd_day) = cur.fetchall()[0]
    return sex, bd_year, bd_mon, bd_day
 def get_unit(self):
     con = sql.connect(database.resource_path('sr_legacy/sr_legacy.db'))
     cur = con.cursor()
     sql_stmt = ('SELECT units ' 'FROM nutr_def ' 'WHERE id = ?')
     cur.execute(sql_stmt, [self.nut_id])
     unit = cur.fetchall()[0][0]
     con.commit()
     con.close()
     return unit
def get_all_food_ids():
    con = sql.connect(database.resource_path('sr_legacy/sr_legacy.db'))
    cur = con.cursor()
    cur.execute("SELECT id FROM food_des")
    food_list = cur.fetchall()

    food_ids = [f[0] for f in food_list]

    return food_ids
def get_nutrition(person, food_ids, food_amounts):
    # Sort input lists according to food ids in ascending order
    if len(food_amounts) == 0:
        return get_empty_nutrition(person)
    food_tups = sorted(zip(food_ids, food_amounts))
    food_ids, food_amounts = (list(food_tup) for food_tup in zip(*food_tups))
    sorted_nuts = sorted(person.nuts, key=lambda n: int(n.nut_id))
    nut_ids = [nut.nut_id for nut in sorted_nuts]
    nut_names = [nut.name for nut in sorted_nuts]
    units = database.get_nutrition_units(nut_ids)

    con = sql.connect(database.resource_path('sr_legacy/sr_legacy.db'))
    cur = con.cursor()
    sql_stmt = ('SELECT amount '
                'FROM nut_data WHERE food_id IN (' +
                (len(food_ids) - 1) * '?, ' + '?) '
                'AND nut_id IN (' + (len(nut_ids) - 1) * '?, ' + '?) '
                'ORDER BY food_id, nut_id')
    cur.execute(sql_stmt, food_ids + nut_ids)
    nut_amounts = np.array(cur.fetchall())

    # Reshape array into matrix, where each row is a food and each column a nutrient
    nut_amounts = nut_amounts.reshape(len(food_ids), len(nut_ids))

    # Check if database lacks a value for each nutrient for all foods and record for later.
    # If every selected food lacks a value for a given nutrient, we display No data.
    # If one or more selected foods have a value, even if the rest have no value in the database,
    # we treat the NULL value in the database as 0 and add them.
    nut_has_data = check_if_sparse_nutrient(nut_amounts)

    nut_amounts[nut_amounts == None] = 0

    # Sum amounts for each respective nutrient given each amount of food
    food_amounts = np.reshape(food_amounts, (len(food_amounts), 1))
    nut_amounts = sum(food_amounts * (nut_amounts / DB_SCALER))

    nutrition = []
    for nut_name, nut_amount, has_data, unit in zip(nut_names, nut_amounts,
                                                    nut_has_data, units):
        if has_data:
            dv = calculate_dv(person, nut_name, nut_amount)
            nutrition.append({
                'name': nut_name,
                'amount': nut_amount,
                'unit': unit[0],
                'percent': dv
            })
        else:
            nutrition.append({
                'name': nut_name,
                'amount': None,
                'unit': unit[0],
                'percent': None
            })

    return sort_nutrition(nutrition)
    def populate_nuts_from_db(self):
        con = sql.connect(database.resource_path('spartan.db'))
        cur = con.cursor()
        sql_stmt = ('SELECT * ' 'FROM nuts ' 'ORDER BY rowid')
        for row in cur.execute(sql_stmt):
            self.nuts.append(
                Nutrient(name=row[0], min=row[1], max=row[2], target=row[3]))

        con.commit()
        con.close()
    def remove_foods_from_db(self, food_ids):
        con = sql.connect(database.resource_path('spartan.db'))
        cur = con.cursor()

        foods_tuple = [(food_id, ) for food_id in food_ids]
        sql_stmt = ('DELETE FROM foods ' 'WHERE food_id = ?')

        cur.executemany(sql_stmt, foods_tuple)
        con.commit()
        con.close()
    def populate_foods_from_db(self):
        con = sql.connect(database.resource_path('spartan.db'))
        cur = con.cursor()

        sql_stmt = ('SELECT * ' 'FROM foods ' 'ORDER BY rowid ')

        for row in cur.execute(sql_stmt):
            self.foods.append(Food(*row))

        con.commit()
        con.close()
def update_sex_bd_in_db(sex, year, mon, day):
    con = sql.connect(database.resource_path('spartan.db'))
    cur = con.cursor()

    sql_stmt = ('UPDATE person '
                'SET (sex, bd_year, bd_mon, bd_day) = '
                '(?,?,?,?)')
    parameters = [sex, year, mon, day]
    cur.execute(sql_stmt, parameters)

    con.commit()
    con.close()
def insert_default_person():
    con = sql.connect(database.resource_path('spartan.db'))
    cur = con.cursor()

    sql_stmt = (
        'INSERT INTO person '
        'VALUES (?,?,?,?) '
    )
    cur.execute(sql_stmt, [None, None, None, None])

    con.commit()
    con.close()
def insert_nuts():
    con = sql.connect(database.resource_path('spartan.db'))
    cur = con.cursor()

    sql_stmt = (
        'INSERT INTO nuts '
        'VALUES (?,?,?,?)'
    )
    for nut_name in req.nut_names:
        parameters = [nut_name, None, None, None]
        cur.execute(sql_stmt, parameters)

    con.commit()
    con.close()
    def make_nutrition_matrix(self):
        nut_ids = [nut.nut_id for nut in self.nuts]
        food_ids = [food.food_id for food in self.foods]

        # Due to sqlite3 limitations, we must batch large queries
        food_batch_size = SQL_VARIABLE_LIMIT - len(nut_ids)
        q, final_batch_size = divmod(len(food_ids), food_batch_size)
        n_batches = q + bool(final_batch_size)

        con = sql.connect(database.resource_path('sr_legacy/sr_legacy.db'))
        cur = con.cursor()
        nut_data = []

        # Get nutritional values for each of the nutrients for each user's food.
        # We must programmatically generate a SQL statement with a variable length number of parameters
        # since food_ids and nut_ids vary depending on user settings
        if n_batches > 1:
            for batch in range(n_batches - 1):
                sql_stmnt = ('SELECT amount '
                             'FROM nut_data '
                             'WHERE food_id IN (?' +
                             (food_batch_size - 1) * ',?' + ') '
                             'AND nut_id IN (?' + (len(nut_ids) - 1) * ',?' +
                             ')'
                             'ORDER BY food_id, nut_id')

                batch_start = batch * food_batch_size
                batch_end = batch * food_batch_size + food_batch_size

                cur.execute(sql_stmnt,
                            food_ids[batch_start:batch_end] + nut_ids)
                nut_data = nut_data + cur.fetchall()

        sql_stmnt = ('SELECT amount '
                     'FROM nut_data '
                     'WHERE food_id IN (?' + (final_batch_size - 1) * ',?' +
                     ') '
                     'AND nut_id IN (?' + (len(nut_ids) - 1) * ',?' + ')'
                     'ORDER BY food_id, nut_id')

        if n_batches > 1:
            batch_start = batch_end
        else:
            batch_start = 0
        cur.execute(sql_stmnt, food_ids[batch_start:] + nut_ids)

        nut_data = nut_data + cur.fetchall()

        self.nutrition_matrix = self.format_nutrition_matrix(nut_data)
def update_nuts_in_db(nutrients):
    con = sql.connect(database.resource_path('spartan.db'))
    cur = con.cursor()
    for nutrient in nutrients:
        sql_stmt = ('UPDATE nuts '
                    'SET (min, max, target) = '
                    '(?,?,?) '
                    'WHERE name = ?')
        parameters = [
            nutrient.min, nutrient.max, nutrient.target, nutrient.name
        ]
        cur.execute(sql_stmt, parameters)

    con.commit()
    con.close()
    def add_food_to_db(self, food):
        con = sql.connect(database.resource_path('spartan.db'))
        cur = con.cursor()

        # Store everything but selectable units, as this is a dynamic list
        food_vars = list(vars(food).keys())
        food_vars.remove('selectable_units')
        food_tuple = str(tuple(food_vars))

        food_values = [getattr(food, var) for var in food_vars]
        sql_stmt = ('INSERT INTO foods' + food_tuple + ''
                    'VALUES (' + (len(food_vars) - 1) * '?,' + '?)')

        cur.execute(sql_stmt, food_values)
        con.commit()
        con.close()
    def update_food_in_user_db(self, food):
        con = sql.connect(database.resource_path('spartan.db'))
        cur = con.cursor()

        food_vars = list(vars(food).keys())
        food_vars.remove('selectable_units')
        food_tuple = str(tuple(food_vars))
        food_values = [getattr(food, var) for var in food_vars]

        # Tuple comes from our dict of attr strings, so no need to sanitize
        sql_stmt = ("UPDATE foods "
                    "SET " + food_tuple + " = "
                    "(" + (len(food_values) - 1) * "?," + "?)"
                    "WHERE food_id = ?")

        cur.execute(sql_stmt, food_values + [food.food_id])
        con.commit()
        con.close()
    def filter_foods(self, foods, fd_res):
        food_ids = [food.food_id for food in foods]

        food_id_batches, fd_grps = [], []
        for i in range(0, len(food_ids), SQL_VARIABLE_LIMIT):
            food_id_batches.append(food_ids[i:i + SQL_VARIABLE_LIMIT])

        con = sql.connect(database.resource_path('sr_legacy/sr_legacy.db'))
        cur = con.cursor()

        for batch in food_id_batches:
            sql_stmnt = ('SELECT food_group_id '
                         'FROM food_des '
                         'WHERE id IN (?' + (len(batch) - 1) * ',?' + ') '
                         'ORDER BY id ')
            cur.execute(sql_stmnt, batch)
            fd_grps = fd_grps + cur.fetchall()

        filtered_foods = [
            food for fd_grp, food in zip(fd_grps, foods)
            if fd_grp[0] not in fd_res
        ]
        return filtered_foods