Add with all current work
This commit is contained in:
commit
6010e067e8
|
@ -0,0 +1 @@
|
|||
developers.sqlite
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/bash
|
||||
|
||||
#set -e
|
||||
|
||||
DATABASE_URL=$(realpath "./developers.sqlite")
|
||||
|
||||
createUUID () {
|
||||
uuidgen | tr '[:upper:]' '[:lower:]'
|
||||
}
|
||||
|
||||
db () {
|
||||
sqlite3 "${DATABASE_URL}" "${1}"
|
||||
}
|
||||
|
||||
setup () {
|
||||
cat "./setup.sql" | sqlite3 "${DATABASE_URL}"
|
||||
echo "Setup ${DATABASE_URL}..."
|
||||
}
|
||||
|
||||
setup
|
|
@ -0,0 +1,203 @@
|
|||
#!/bin/bash
|
||||
|
||||
import sqlite3
|
||||
import csv
|
||||
import os
|
||||
from uuid import uuid4
|
||||
from os import path
|
||||
|
||||
RECIPES='recipes/'
|
||||
SUPPLY='supply.csv'
|
||||
|
||||
con = sqlite3.connect('developers.sqlite')
|
||||
c = con.cursor()
|
||||
|
||||
def uuid () :
|
||||
return str(uuid4())
|
||||
|
||||
def getRecipe (name) :
|
||||
query="SELECT recipe_id FROM recipes WHERE (name = LOWER(?)) LIMIT 1;"
|
||||
res = c.execute(query, (name,))
|
||||
return c.fetchone()
|
||||
|
||||
def hasRecipe (name) :
|
||||
recipe = getRecipe(name)
|
||||
if recipe is not None:
|
||||
return recipe[0]
|
||||
return ''
|
||||
|
||||
def createRecipe (name) :
|
||||
id=uuid()
|
||||
query="INSERT OR IGNORE INTO recipes (recipe_id, name) VALUES (?, LOWER(?));"
|
||||
c.execute(query, (id, name,))
|
||||
con.commit()
|
||||
return id
|
||||
|
||||
def getChemical (chemical) :
|
||||
query="SELECT chemical_id FROM chemicals WHERE (name = LOWER(?)) LIMIT 1;"
|
||||
res = c.execute(query, (chemical,))
|
||||
return c.fetchone()
|
||||
|
||||
def hasChemical (chemical) :
|
||||
chemical = getChemical(chemical)
|
||||
if chemical is not None:
|
||||
return chemical[0]
|
||||
return ''
|
||||
|
||||
def createChemical (chemical) :
|
||||
id=uuid()
|
||||
query="INSERT OR IGNORE INTO chemicals (chemical_id, name) VALUES (?, LOWER(?));"
|
||||
c.execute(query, (id, chemical,))
|
||||
con.commit()
|
||||
return id
|
||||
|
||||
def ensureChemical (chemical) :
|
||||
chemical_id = hasChemical(chemical)
|
||||
if chemical_id == '' :
|
||||
chemical_id = createChemical(chemical)
|
||||
return chemical_id
|
||||
|
||||
def getSupply (url) :
|
||||
query="SELECT supply_id FROM supply WHERE (url = ?) LIMIT 1;"
|
||||
res = c.execute(query, (url,))
|
||||
return c.fetchone()
|
||||
|
||||
def hasSupply (url) :
|
||||
supply = getSupply(url)
|
||||
if supply is not None:
|
||||
return supply[0]
|
||||
return ''
|
||||
|
||||
def createSupply (chemical_id, url, g, ml, price) :
|
||||
id=uuid()
|
||||
query="INSERT OR IGNORE INTO supply (supply_id,chemical_id,url,grams,milliliters,price) VALUES (?,?,?,?,?,?);"
|
||||
c.execute(query, (id,chemical_id,url,g,ml,price,))
|
||||
con.commit()
|
||||
return id
|
||||
|
||||
def ensureSupply (chemical_id, url, g, ml, price) :
|
||||
supply_id = hasSupply(url)
|
||||
if supply_id == '' :
|
||||
supply_id = createSupply(chemical_id, url, g, ml, price)
|
||||
return supply_id
|
||||
|
||||
def displaySupply (supply_id, chemical) :
|
||||
query="SELECT round((price/100.0)/grams, 2) FROM supply WHERE (supply_id = ?);"
|
||||
res = c.execute(query, (supply_id,))
|
||||
data = c.fetchone()
|
||||
ratio = data[0]
|
||||
print(f"{chemical}: {ratio} $/g")
|
||||
|
||||
def getRecipe (recipe) :
|
||||
query="SELECT recipe_id FROM recipes WHERE (name = LOWER(?)) LIMIT 1;"
|
||||
res = c.execute(query, (recipe,))
|
||||
return c.fetchone()
|
||||
|
||||
def hasRecipe (recipe) :
|
||||
recipe = getRecipe(recipe)
|
||||
if recipe is not None:
|
||||
return recipe[0]
|
||||
return ''
|
||||
|
||||
def createComponent (chemical, recipe_id, chemical_id, g, ml, makes, note) :
|
||||
id = uuid()
|
||||
query="INSERT OR IGNORE INTO components (component_id,recipe_id,chemical_id,grams,milliliters,makes,note) VALUES (?,?,?,?,?,?,?);"
|
||||
c.execute(query, (id, recipe_id, chemical_id, g, ml, makes, note))
|
||||
con.commit()
|
||||
val=f"{g}g" if g != 'NULL' else f"{ml}ml"
|
||||
print(f"Added component {chemical} {val}")
|
||||
|
||||
def createRecipe (recipe) :
|
||||
id=uuid()
|
||||
query="INSERT OR IGNORE INTO recipes (recipe_id, name) VALUES (?, ?);"
|
||||
c.execute(query, (id, recipe,))
|
||||
con.commit()
|
||||
return id
|
||||
|
||||
def importRecipe (filePath) :
|
||||
name = path.basename(filePath).replace('.csv', '').replace('_', ' ')
|
||||
recipe_id = hasRecipe(name)
|
||||
|
||||
if recipe_id != '' :
|
||||
print(f"Recipe {name} already exists")
|
||||
return
|
||||
|
||||
recipe_id = createRecipe(name)
|
||||
|
||||
with open(filePath, newline='') as csvfile:
|
||||
reader = csv.reader(csvfile, delimiter=',', quotechar='|')
|
||||
for row in reader:
|
||||
chemical=row[0]
|
||||
if chemical == 'chemical' :
|
||||
continue
|
||||
g=float(row[1]) if row[1] != '' else 'NULL'
|
||||
ml=float(row[2]) if row[2] != '' else 'NULL'
|
||||
makes=int(row[3])
|
||||
note=row[4]
|
||||
chemical_id=ensureChemical(chemical)
|
||||
createComponent(chemical, recipe_id, chemical_id, g, ml, makes, note)
|
||||
print(f"Imported {name}")
|
||||
|
||||
def displayCents (val) :
|
||||
return '${:,.2f}'.format(val / 100.0)
|
||||
|
||||
def displayCost (ml) :
|
||||
query = "SELECT recipe_id,UPPER(name) FROM recipes ORDER BY name ASC;"
|
||||
c.execute(query)
|
||||
rows = c.fetchall()
|
||||
for row in rows:
|
||||
recipe = row[1]
|
||||
print(f"{recipe}: {ml/1000} liters")
|
||||
query = """SELECT a.name, (c.grams * (s.price/s.grams)) / c.makes, (c.grams/c.makes) FROM components AS c
|
||||
INNER JOIN supply AS s
|
||||
ON c.chemical_id = s.chemical_id
|
||||
INNER JOIN chemicals AS a
|
||||
ON c.chemical_id = a.chemical_id
|
||||
WHERE c.recipe_id = ?;"""
|
||||
|
||||
c.execute(query, (row[0],))
|
||||
components = c.fetchall()
|
||||
|
||||
total = 0
|
||||
for component in components:
|
||||
name = component[0]
|
||||
price = component[1] * ml
|
||||
grams = component[2] * ml
|
||||
total += price
|
||||
print(f"{name} : [{grams}g] {displayCents(price)}")
|
||||
print("------")
|
||||
print(f"Total: {displayCents(total)}")
|
||||
print("------")
|
||||
|
||||
print('-------')
|
||||
print('SUPPLY')
|
||||
print('-------')
|
||||
|
||||
with open(SUPPLY, newline='') as csvfile:
|
||||
reader = csv.reader(csvfile, delimiter=',', quotechar='|')
|
||||
for row in reader:
|
||||
chemical=row[0]
|
||||
if chemical == 'chemical' :
|
||||
continue
|
||||
url=row[1]
|
||||
g=float(row[2]) if row[2] != '' else 'NULL'
|
||||
ml=float(row[3]) if row[3] != '' else 'NULL'
|
||||
price=int(row[4])
|
||||
chemical_id = ensureChemical(chemical)
|
||||
supply_id = ensureSupply(chemical_id, url, g, ml, price)
|
||||
displaySupply(supply_id, chemical)
|
||||
|
||||
print('-------')
|
||||
print('RECIPES')
|
||||
print('-------')
|
||||
|
||||
for recipe in os.listdir(RECIPES):
|
||||
if recipe.endswith('.csv') :
|
||||
filePath=f'{RECIPES}{recipe}'
|
||||
importRecipe(filePath)
|
||||
|
||||
print('----')
|
||||
print('COST')
|
||||
print('----')
|
||||
|
||||
displayCost(3785) #gallon
|
|
@ -0,0 +1,179 @@
|
|||
#!/bin/bash
|
||||
|
||||
rm -f ./developers.sqlite
|
||||
|
||||
source ./common.sh
|
||||
|
||||
RECIPES=./recipes
|
||||
FILES=$(mktemp)
|
||||
SUPPLY=$(realpath ./supply.csv)
|
||||
|
||||
mkdir -p recipes
|
||||
|
||||
hasRecipe () {
|
||||
query="SELECT recipe_id FROM recipes WHERE (name = '${1}') LIMIT 1;"
|
||||
db "${query}"
|
||||
}
|
||||
|
||||
createRecipe () {
|
||||
id=$(createUUID)
|
||||
name="${1}"
|
||||
query="INSERT OR IGNORE INTO recipes (recipe_id, name) VALUES ('${id}', '${name}');"
|
||||
db "${query}"
|
||||
echo "${id}"
|
||||
}
|
||||
|
||||
hasChemical () {
|
||||
query="SELECT chemical_id FROM chemicals WHERE (name = '${1}') LIMIT 1;"
|
||||
db "${query}"
|
||||
}
|
||||
|
||||
createChemical () {
|
||||
chemical_id="$(createUUID)"
|
||||
query="INSERT OR IGNORE INTO chemicals (chemical_id, name) VALUES ('${chemical_id}', '${1}');"
|
||||
db "${query}"
|
||||
}
|
||||
|
||||
chemical () {
|
||||
chemical_id=$(hasChemical "${1}")
|
||||
if [[ "${chemical_id}" == "" ]]; then
|
||||
chemical_id=$(createChemical "${1}");
|
||||
fi
|
||||
echo "${chemical_id}"
|
||||
}
|
||||
|
||||
hasSupply () {
|
||||
query="SELECT supply_id FROM supply WHERE (url = '${1}') LIMIT 1;"
|
||||
db "${query}"
|
||||
}
|
||||
|
||||
component () {
|
||||
cols="${1}"
|
||||
IFS=',' read -ra VALS <<< "${2}"
|
||||
recipe_id="${3}"
|
||||
id=$(createUUID)
|
||||
query="INSERT OR IGNORE INTO components (component_id,recipe_id,${cols}) VALUES ('${id}','${recipe_id}',"
|
||||
before=""
|
||||
first=""
|
||||
for i in "${VALS[@]}"; do
|
||||
val=NULL
|
||||
if [[ "${first}" == "" ]]; then
|
||||
chemical_id=$(chemical "${i}")
|
||||
val="'${chemical_id}'"
|
||||
first="completed"
|
||||
elif [[ "${i}" != "" ]]; then
|
||||
val="'${i}'"
|
||||
fi
|
||||
query="${query}${before}${val}"
|
||||
before=","
|
||||
done
|
||||
|
||||
query="${query});"
|
||||
echo "${query}"
|
||||
db "${query}"
|
||||
}
|
||||
|
||||
import () {
|
||||
name=$(basename "${1}")
|
||||
name=${name%.*}
|
||||
name=$(echo ${name} | sed 's/_/ /g')
|
||||
|
||||
recipe_id=$(hasRecipe "${name}")
|
||||
if [[ "${recipe_id}" != "" ]]; then
|
||||
echo "${name} recipe already exists."
|
||||
return
|
||||
else
|
||||
recipe_id=$(createRecipe "${name}")
|
||||
fi
|
||||
cols="chemical,grams,milliliters,makes"
|
||||
while read line; do
|
||||
line=$(echo "${line}" | xargs)
|
||||
if [[ "${line}" == "chemical"* ]]; then
|
||||
cols="${line}"
|
||||
cols="${cols/chemical,/chemical_id,}"
|
||||
continue
|
||||
fi
|
||||
component "${cols}" "${line}" "${recipe_id}"
|
||||
done < "${1}"
|
||||
|
||||
echo "Imported ${name}."
|
||||
}
|
||||
|
||||
list () {
|
||||
echo "RECIPES:"
|
||||
db "SELECT name FROM recipes ORDER BY name DESC;"
|
||||
echo "CHEMICALS:"
|
||||
db "SELECT name FROM chemicals ORDER BY name DESC"
|
||||
}
|
||||
|
||||
supply () {
|
||||
line=$(echo "${1}" | xargs)
|
||||
first=""
|
||||
before=""
|
||||
|
||||
if [[ "${line}" == "chemical,"* ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
chemical=$(echo "${line}" | awk -F',' '{print $1}')
|
||||
url=$(echo "${line}" | awk -F',' '{print $2}')
|
||||
|
||||
chemical_id=$(chemical "${chemical}")
|
||||
has_supply=$(hasSupply "${url}")
|
||||
|
||||
if [[ "${has_supply}" != "" ]]; then
|
||||
return
|
||||
fi
|
||||
supply_id=$(createUUID)
|
||||
query="INSERT OR IGNORE INTO supply (supply_id,chemical_id,url,grams,milliliters,price) VALUES ('${supply_id}','${chemical_id}',"
|
||||
IFS=',' read -ra VALS <<< "${line}"
|
||||
for i in "${VALS[@]}"; do
|
||||
if [[ "${first}" == "" ]]; then
|
||||
first="complete"
|
||||
continue
|
||||
fi
|
||||
val=NULL
|
||||
if [[ "${i}" != "" ]]; then
|
||||
val="'${i}'"
|
||||
fi
|
||||
query="${query}${before}${val}"
|
||||
before=","
|
||||
done
|
||||
query="${query});"
|
||||
#echo "${query}"
|
||||
|
||||
db "${query}"
|
||||
ratio=$(db "SELECT round((price/100.0)/grams, 2) FROM supply WHERE (supply_id = '${supply_id}');")
|
||||
echo "${chemical}: ${ratio} $/g"
|
||||
}
|
||||
|
||||
priceRecipe () {
|
||||
recipesList=$(mktemp)
|
||||
query="SELECT r.recipe_id FROM recipes AS r ORDER BY r.name;"
|
||||
db "${query}" > "${recipesList}"
|
||||
|
||||
while read id; do
|
||||
db "SELECT name FROM recipes WHERE recipe_id = '${id}' LIMIT 1;"
|
||||
echo "---"
|
||||
db "SELECT COUNT(*) FROM components WHERE recipe_id = '${id}';"
|
||||
query="SELECT ch.name FROM components AS c
|
||||
INNER JOIN chemicals AS ch ON ch.chemical_id = c.chemical_id
|
||||
WHERE c.recipe_id = '${id}';"
|
||||
db "${query}"
|
||||
echo " "
|
||||
done < "${recipesList}"
|
||||
}
|
||||
|
||||
ls -1 "${RECIPES}/"*.csv > "${FILES}"
|
||||
|
||||
while read file; do
|
||||
import "${file}"
|
||||
done < "${FILES}"
|
||||
echo "---"
|
||||
while read line; do
|
||||
supply "${line}"
|
||||
done < "${SUPPLY}"
|
||||
echo "---"
|
||||
|
||||
priceRecipe
|
||||
#list
|
|
@ -0,0 +1,7 @@
|
|||
chemical,grams,milliliters,makes,note
|
||||
Water,,750,1000,
|
||||
Metol,2,,1000,
|
||||
Sodium Sulfite (anhydrous),80,,1000,
|
||||
Hydroquinone,4,,1000,
|
||||
Borax,4,,1000,
|
||||
Potassium Bromide,0.5,,1000,
|
|
|
@ -0,0 +1,8 @@
|
|||
chemical,grams,milliliters,makes,note
|
||||
Water,,700,1000,
|
||||
Phenidone,0.25,,1000,
|
||||
Hydroquinone,5,,1000,
|
||||
Glycin,1.5,,1000,
|
||||
Sodium Sulfite (anhydrous),125,,1000,
|
||||
Borax,2.5,,1000,granular
|
||||
Potassium Bromide,0.5,,1000,
|
|
|
@ -0,0 +1,7 @@
|
|||
chemical,grams,milliliters,makes,note
|
||||
Water,,500,1000,
|
||||
Metol,2,,1000,
|
||||
Sodium Sulfite (anhydrous),90,,1000,
|
||||
Sodium Carbonate (monohydrate),52.5,,1000,
|
||||
Hydroquinone,8,,1000,
|
||||
Potassium Bromide,5,,1000,
|
|
|
@ -0,0 +1,6 @@
|
|||
chemical,grams,milliliters,makes,note
|
||||
Water,,750,1000,
|
||||
Metol,2,,1000,
|
||||
Sodium Sulfite (anhydrous),100,,1000,
|
||||
Hydroquinone,5,,1000,
|
||||
Borax,2,,1000,
|
|
|
@ -0,0 +1,6 @@
|
|||
chemical,grams,milliliters,makes,note
|
||||
Water,,850,1000,
|
||||
Sodium Sulfite,10,,1000,
|
||||
Diethylenetriaminepentaacetic Acid Pentasodium Salt,1,,1000,
|
||||
Sodium Metaborate,4.0,,100,(8 mol)
|
||||
4-Hydroxymethyl-4-Methyl-1-Phenyl-3-Pyrazolidione,0.2,,1000,
|
|
|
@ -0,0 +1,4 @@
|
|||
chemical,grams,milliliters,makes,note
|
||||
Sodium Sulfite,75,,1000,
|
||||
Sodium Metabisulfite,3.5,,1000,
|
||||
Sodium Isoascorbate,12,,1000,
|
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
rm -rf developers.sqlite
|
||||
|
||||
source common.sh
|
||||
|
||||
python3 import.py
|
|
@ -0,0 +1,31 @@
|
|||
CREATE TABLE IF NOT EXISTS chemicals (
|
||||
chemical_id CHAR(36) PRIMARY KEY,
|
||||
name TEXT UNIQUE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS recipes (
|
||||
recipe_id CHAR(36) PRIMARY KEY,
|
||||
name TEXT UNIQUE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS components (
|
||||
component_id CHAR(36) PRIMARY KEY,
|
||||
recipe_id CHAR(36),
|
||||
chemical_id CHAR(36),
|
||||
grams REAL,
|
||||
milliliters REAL,
|
||||
makes REAL,
|
||||
note TEXT,
|
||||
CONSTRAINT fk_recipes FOREIGN KEY (recipe_id) REFERENCES recipes(recipe_id),
|
||||
CONSTRAINT fk_chemicals FOREIGN KEY (chemical_id) REFERENCES chemicals(chemical_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS supply (
|
||||
supply_id CHAR(36) PRIMARY KEY,
|
||||
chemical_id CHAR(36),
|
||||
url TEXT UNIQUE,
|
||||
grams REAL,
|
||||
milliliters REAL,
|
||||
price INTEGER,
|
||||
CONSTRAINT fk_chemicals FOREIGN KEY (chemical_id) REFERENCES chemicals(chemical_id)
|
||||
);
|
|
@ -0,0 +1,12 @@
|
|||
chemical,url,grams,milliliters,price
|
||||
Sodium Sulfite (anhydrous),https://www.bhphotovideo.com/c/product/124092-REG/Photographers_Formulary_10_1340_1LB_Sodium_Sulfite_1.html,453.592,,695
|
||||
Sodium Carbonate (monohydrate),https://www.bhphotovideo.com/c/product/124044-REG/Photographers_Formulary_10_1190_1LB_Sodium_Carbonate_Monohydrate.html,453.592,,995
|
||||
Potassium Bromide,https://www.bhphotovideo.com/c/product/123938-REG/Photographers_Formulary_10_0930_1LB_Potassium_Bromide_1.html,453.592,,2195
|
||||
Phenidone,https://www.bhphotovideo.com/c/product/123915-REG/Photographers_Formulary_10_0870_100G_Phenidone_100_Grams.html,100,,2695
|
||||
Metol,https://www.bhphotovideo.com/c/product/123903-REG/Photographers_Formulary_10_0770_100G_Metol_Elon_100.html,100,,1695
|
||||
Hydroquinone,https://www.bhphotovideo.com/c/product/123903-REG/Photographers_Formulary_10_0770_100G_Metol_Elon_100.html,100,,1695
|
||||
Glycin,https://www.bhphotovideo.com/c/product/123868-REG/Photographers_Formulary_10_0610_100G_Glycin_N_Parahydroxyphenyl.html,100,,2395
|
||||
Borax,https://www.bhphotovideo.com/c/product/123755-REG/Photographers_Formulary_10_0260_1LB_Borax_1_lb.html,453.592,,695
|
||||
Hydroquinone,https://www.bhphotovideo.com/c/product/123887-REG/Photographers_Formulary_10_0670_100G_Hydroquinone_100_Grams.html,100,,895
|
||||
Sodium Metabisulfite,https://www.bhphotovideo.com/c/product/124063-REG/Photographers_Formulary_10_1280_100G_Sodium_Metabisulfite_100g.html,100,,595
|
||||
Sodium Metaborate,https://www.bhphotovideo.com/c/product/124068-REG/Photographers_Formulary_10_1285_1LB_Sodium_Metaborate_Balanced_Alkali.html,453.592,,1195
|
|
Loading…
Reference in New Issue