Commit 96cf01a0 authored by Adam Blank's avatar Adam Blank
Browse files

Update main.py, chem.py, README.md, manifest.json files

parents
No related merge requests found
Showing with 182 additions and 0 deletions
+182 -0
# Instructions
In this assignment, we're going to be working with **Flask**, a "micro web framework" for Python. The big idea is that flask allows you to write and use python code to generate and interact with websites!
We could spend a whole course talking about Flask, but for this assignment we're going to focus on one thing: *working with form input*. To do that, we're going to use the chemical equation balancer that **you've** already written!
The goal of this assignment is to get our flask app working, so that when we enter an equation into the form and click the "Balance" button, the correct balanced equation is succesfully printed out.
You might notice that some of the functions in your `main.py` file have an "`@app.route(...)`" above them -- that's part of Flask! All that means is that when someone tries to go to the path in the parentheses, the function below should get run, and its output value should be displayed. That means that a lot of our Flask functions are actually returning HTML strings! If you haven't seen HTML, don't worry, we've written most of it for you.
When you fill out an HTML form and hit a submit button, the data in the form is then pulled out and sent to the next webpage. There are different ways of sending that data; we've set up our web app to use "POST requests". Using the `request` library, we're able to retrieve form information, using Python code.
## Steps
1. Fill in the relevant functions: `display`, `parse`, and `parse_side`. These are mostly a continuation of some of the functions you wrote yesterday, just using different types of data.
2. Write the TODO code in the `page` method.
3. In the `balance` function, fill in the two variables at the very beginning of the function. To access form data, you'll want to use the `request.form` variable, and the "name" field of the form element. So, to get the data in the reactants field, you would write `request.form['reactants']`.
4. Choose **one** HTML feature you would like to add to our website. This can be changing the background color, updating the fonts, stylizing our form, or anything else you can think of! Find the relevant HTML code, and add it to our Flask app to see what happens!
## Creative Tasks
HTML is an awesome way to add an artistic flair to your programming skills. Between Flask and HTML, this pretty much turns into a sandbox assignment, and you can go as crazy as you want. Try adding style to the web page, adding more features based on code you wrote in Python, or both!
\ No newline at end of file
### Copy/Paste your working chemical equations code here!
\ No newline at end of file
from flask import Flask, request
import chem
app = Flask(__name__)
UPPER = 1
LOWER = 2
NUMBER = 3
# The HTML used to display our home page! Pay special attention to the "name"
# fields for our input forms -- that's how a function can look up data.
HEADER = "<h1 style='margin-bottom: 10px'>Chemical Equation Balancer</h1><style>li { margin-left: -25px; }</style>"
FORM = '''
<form action="/input" method="post">
<input
id="reactants"
name="reactants"
placeholder="H2 + O2"
style="width: 200px"
>
&rarr;
<input
id="products"
placeholder="H2O"
name="products"
style="width: 200px"
>
&nbsp;&nbsp;&nbsp;&nbsp;
<input type="submit" value="Balance">
</form>
<hr>
'''
history = []
def page(msg):
result = HEADER + FORM + "<ul>"
msgs = history
if msg and msg not in history:
msgs += [msg]
## TODO: Add the elements in `msgs` to the HTML list by
## looping over the list, and adding the items to <li></li>
## tags.
result += "</ul>"
if msg or history:
result += "<br><br>"
## TODO: Update our history. If page() was given a new message,
## and that message is not already in history, then add it.
return result
def error(msg, r, p):
reactsd = display_side(r)
prodsd = display_side(p)
return page(
f"<b>{reactsd} &rarr; {prodsd}</b> " + msg
)
def letter_type(x):
if len(x) == 0:
return None
else:
x = x[0]
if x.isupper():
return UPPER
elif x.islower():
return LOWER
elif x.isnumeric():
return NUMBER
def split(element):
element = list(element)
if not element:
return []
partial = element.pop(0)
prev_type = letter_type(partial)
result = []
while element or partial:
next_type = letter_type(element)
if not next_type or next_type == UPPER or\
(prev_type != NUMBER and next_type == NUMBER):
result.append(partial)
partial = ""
if element:
partial += element.pop(0)
prev_type = next_type
return result
# Given a compound, return the appropriate HTML to display that compound.
# To display subscripts in HTML, put the number in between <sub> </sub>,
# so H2O would look like H<sub>2</sub>O
def display(element):
element = split(element)
return ""
def display_side(side, sol=None):
side = side.replace(" ", "").split("+")
for i in range(len(side)):
side[i] = display(side[i])
if sol and sol[i] != 1:
side[i] = str(sol[i]) + side[i]
return " + ".join(side)
# Take in a "list element" and convert it into a list of
# tuples that our chemical equation code can work with
# Ex: ['H', '2'] --> [('H', 2)]
# Ex: ['C', 'O', '2'] --> [('C', 1), ('O', 2)]
def parse(element):
element = split(element)
return []
# Given the chemical equation written in one of the inputs on the
# homepage, convert it into a list of tuple (you probably want to
# use the parse you wrote here!)
# Ex: 'H2 + O2' --> [[('H', 2)], [('O', 2)]]
# Ex: 'H2O' --> [[('H', 2), ('O', 1)]]
def parse_side(side):
return []
@app.route("/input", methods=['POST'])
def balance():
reactant_form_data = "????"# Fill this in!
product_form_data = "????" # Fill this in!
reacts = parse_side(reactant_form_data)
prods = parse_side(product_form_data)
atoms1 = chem.find_atoms(reacts)
atoms2 = chem.find_atoms(prods)
if not atoms1 or set(atoms1) != set(atoms2):
return error(
"is not a valid chemical equation.",
reactant_form_data,
product_form_data
)
sol = chem.solve(chem.construct_matrix(atoms1, reacts, prods))
if not sol or float('inf') in sol or float('nan') in sol:
return error(
"does not have a valid solution.",
reactant_form_data,
product_form_data
)
sol = [int(x) for x in sol]
reactsd = display_side(reactant_form_data, sol)
prodsd = display_side(product_form_data, sol[len(reacts):])
return page(f"The balanced equation is <b>{reactsd} &rarr; {prodsd}</b>.")
@app.route("/")
def homepage():
return page("")
app.run(host='0.0.0.0', port=81, debug=True)
{
"upload": ["main.py"]
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment