A document from MCS 275 Spring 2022, instructor David Dumas. You can also get the notebook file.

# MCS 275 Spring 2022 Worksheet 13 Solutions¶

• Course instructor: David Dumas
• Solutions prepared by: Johnny Joyce

## Topics¶

This worksheet focuses on HTML, CSS, and the basics of the Python web framework Flask. (We'll continue working on Flask in the upcoming week, with more Flask-related exercises coming in Worksheet 14.)

## Resources¶

These things might be helpful while working on the problems. Remember that for worksheets, we don't strictly limit what resources you can consult, so these are only suggestions.

In MCS 275, all of the following materials are distributed as URLs that link to public web pages:

• Lecture slides, which have URLs like
https://www.dumas.io/teaching/2022/spring/mcs275/slides/lecture35.html
• Worksheets, which have URLs like
https://www.dumas.io/teaching/2022/spring/mcs275/nbview/worksheets/worksheet13.html
• Worksheet solutions, which have URLs like
https://www.dumas.io/teaching/2022/spring/mcs275/nbview/worksheets/worksheet13soln.html
• Homework assignments, which have URLs like
https://www.dumas.io/teaching/2022/spring/mcs275/nbview/homework/homework11.html
• Homework solutions, which have URLs like
https://www.dumas.io/teaching/2022/spring/mcs275/nbview/homework/homework11soln.html
• Projects, which have URLs like
https://www.dumas.io/teaching/2022/spring/mcs275/nbview/projects/project3.html

Write a Python script mcs275spring2022.py that generates an HTML file (writing it to mcs275spring2022.html) that contains a header, sections for each class of course material, and lists of the individual documents, as shown below. (The page will be quite long, so the image below shows its contents in two columns instead of one very tall image. However, the actual page should have just one column of content.) Each list item should be a link to the actual course document.

Note: For this program, you're not using Flask. You're making a program that opens and writes to a text file. This is testing your HTML knowledge and your string handling skills.

# Solution¶

In [ ]:
html = """
<!doctype html>
<html>
<title>MCS 275 Spring 2022</title>
<body>
<h1>MCS 275 Spring 2022</h1>
<div>
<h2>Lectures</h2>
<ul>
"""

for i in range(1,45):
html += "<li><a href=\"https://www.dumas.io/teaching/2022/spring/mcs275/slides/lecture{0}.html\">Lecture {0}</a></li>\n".format(i)

# Write worksheets
html += """
</ul>
</div>
<div>
<h2>Worksheets</h2>
<ul>
"""
for i in range(1,15):
html += "<li><a href=\"https://www.dumas.io/teaching/2022/spring/mcs275/nbview/worksheets/worksheet{0}.html\">Worksheet {0}</a></li>\n".format(i))

# Write worksheet solutions
html += """
</ul>
</div>
<div>
<h2>Worksheet Solutions</h2>
<ul>
"""
for i in range(1,15):
html += "<li><a href=\"https://www.dumas.io/teaching/2022/spring/mcs275/nbview/worksheets/worksheet{0}soln.html\">Worksheet {0} Solutions</a></li>\n".format(i))

# Write homeworks
html += """
</ul>
</div>
<div>
<h2>Homework</h2>
<ul>
"""
for i in range(1,15):
html += "<li><a href=\"https://www.dumas.io/teaching/2022/spring/mcs275/nbview/homework/homework{0}.html\">Homework {0}</a></li>\n".format(i)

# Write homework solutions
html += """
</ul>
</div>
<div>
<h2>Homework Solutions</h2>
<ul>
""")
for i in range(1,15):
html += "<li><a href=\"https://www.dumas.io/teaching/2022/spring/mcs275/nbview/homework/homework{0}soln.html\">Homework {0} Solutions</a></li>\n".format(i))

# Write projects
html += """
</ul>
</div>
<div>
<h2>Projects</h2>
<ul>
"""
for i in range(1,5):
html += "<li><a href=\"https://www.dumas.io/teaching/2022/spring/mcs275/nbview/projects/project{0}.html\">Project {0}</a></li>\n".format(i))
html += """
</ul>
</div>
</body>
</html>
"""

with open("mcs275spring2022.html","w",encoding="UTF-8") as fp:
fp.write(html)


Make the output HTML refer to a stylesheet courselinks.css and then create that stylesheet. Add directives so that the body of the document requests the typeface "Helvetica", and add other rules to make the rendered mcs275spring2022.html look as much as possible like the one below.

Note: The actual typeface in this image isn't Helvetica; my browser substituted a similar typeface because it couldn't find the one the CSS specified.

# Solution¶

To have the HTML file refer to courselinks.css, we add this to the head:

• <link rel="stylesheet" href="courselinks.css">

Inside courselinks.css:

body { font-family: "Helvetica"; color: white; background: #303030; } a { color: #C0FFC0; } h1, h2 { background: #505050; } ul { color: #C0FFC0; background: #603030; } li { background: #303060; }

## 3. Base converter¶

First, let's discuss a feature of Flask that didn't come up in Lecture 35, but will be useful in this problem.

Recall that if app is a flask.Flask object, then the decorator

@app.route("/orthogonal/sauntering/balloon/")
def f():
return "...HTML HERE..."

will arrange that the function f gets called whenever the document /orthogonal/sauntering/balloon is requested from the application (e.g. by you opening http://localhost:8000/orthogonal/sauntering/balloon/ in a web browser).

This is great for fixed URLs, but sometimes you want many similar URLs to all be handled by a single function. Typically, the function would look at certain parts of the URL to decide what to do. For example, in an application that has pages with information about planets, you could define separate functions for each of

/orbital_period/venus/
/orbital_period/earth/
/orbital_period/mars/

but it would be nicer to have a single function that can return a page about the orbital period for any of the planets. Flask supports this with a syntax like

@app.route("/orbital_period/<planet>/")  # part inside < and > brackets is a placeholder
def get_period(planet):     # the string appearing there gets passed as an argument
return "...HTML HERE..."

so that a request for /orbital_period/earth/ will call get_period("earth") while a request for /orbit_period/mars/ will call get_period("mars"). Note that the parameters of the function need to match the names given inside the <...> appearing in the route description (e.g. <planet> in the route description means we need a parameter called planet).

Write a Flask application baseconvert.py that can convert between decimal, binary, and hexadecimal, based on a request encoded as a URL such as

/decimal/120/to/binary/
/hexadecimal/f00f/to/decimal/

with the general syntax being

/INBASE/N/to/OUTBASE/

where INBASE and OUTBASE are each one of decimal, binary, or hexadecimal, and where N is a sequence of digits representing an integer in the number system INBASE.

The application should only have a single route which decides what to do based on parts of the URL.

Thus, for example, a request for /decimal/9/to/binary/ might generate this HTML code as a response:

<!doctype HTML>
<html>
<title>Decimal 9 is binary 1001</title>
<body>
<h1>9 = 0b1001</h1>
</body>
</html>

and for /hexadecimal/1f/to/decimal/, the HTML your application sends as the response might be:

<!doctype HTML>
<html>
<body>
<h1>0x1f = 31</h1>
</body>
</html>

# Solution¶

In [ ]:
from flask import Flask

def make_title(inbase, n, outbase, converted):
'''Helper function for convert. Returns HTML code of title'''
if outbase == "binary" or outbase == "hexadecimal": # If applicable, remove prefixes "0b" or "0x"
converted = str(converted)[2:]
return "<title>{} {} is {} {}</title>".format(inbase, n, outbase, converted)

def make_body(inbase, n, outbase, converted):
'''Helper function for convert. Returns HTML code of body'''
prefix = {"decimal": "", "binary": "0b", "hexadecimal": "0x"}
n = prefix[inbase] + n # If applicable, put prefix "0b" or "0x" in front of the number given by user
return "<h1>{} = {}</h1>".format(n, converted)

@app.route("/<inbase>/<n>/to/<outbase>/") # Each entry inside < > will become an argument for convert()
def convert(inbase, n, outbase):
'''Converts number n from base inbase to base outbase. Returns as HTML code.'''

# First, interpret n as a decimal number (regardless of outbase)
base_dict = {"decimal": 10, "binary": 2, "hexadecimal": 16}
as_decimal = int(n, base_dict[inbase])

# Now convert decimal to required outbase
if outbase == "decimal":
converted = as_decimal
elif outbase == "binary":
converted = bin(as_decimal)
converted = hex(as_decimal)

# Call helper functions. Assemble and return the HTML code
title = make_title(inbase, n, outbase, converted)
body = make_body(inbase, n, outbase, converted)
html = '''
<!doctype HTML>
<html>
<body> {} </body>
</html>
'''.format(title, body)
return html

app.run()

 * Serving Flask app "__main__" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off

 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [14/Apr/2022 14:48:36] "GET / HTTP/1.1" 404 -
127.0.0.1 - - [14/Apr/2022 14:49:00] "GET /binary/1010101010/to/decimal HTTP/1.1" 308 -
127.0.0.1 - - [14/Apr/2022 14:49:00] "GET /binary/1010101010/to/decimal/ HTTP/1.1" 200 -

In [ ]: