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

MCS 275 Spring 2024 Worksheet 13

  • Course instructor: Emily Dumas

Topics

This worksheet focuses on Flask web applications, anonymous functions, and decorators.

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.

1. Get TaskGain or ActiveTask running locally

The Flask application written in lecture was called TaskGain or ActiveTask, depending on which section of MCS 275 you are in. The applications are quite similar, and use a SQLite database to manage a collection of tasks that have owners, privacy settings, state (e.g. "in progress"), and a timestamp of creation or update.

To prepare for the next problem, download a copy of the Flask application for your section and get it running on your computer.

A. Download

The application has a number of files, so you can do it in either of these ways:

List of files for TaskGain

  • taskgain.py - Main program
  • add_sample_tasks.py - Utility to add sample tasks
  • timefmt.py - Module for time formatting
  • static/ - Subdirectory for static files
  • static/taskgain.css - Main stylesheet
  • templates/ - Subdirectory for templates
  • templates/task_list_view.html - Template for task list
  • templates/add_task_form.html - Template for new task form
  • templates/front.html - Template for front page

List of files for ActiveTask

  • activetask.py - Main program
  • add_sample_tasks.py - Utility to add sample tasks
  • timefmt.py - Module for time formatting
  • static/ - Subdirectory for static files
  • static/activetask.css - Main stylesheet
  • templates/ - Subdirectory for templates
  • templates/task_list_view.html - Template for task list
  • templates/add_task.html - Template for new task form
  • templates/front.html - Template for front page

B. Test it out

Open a terminal and cd to the location of the main .py script (taskgain.py or activetask.py). Run that script with Python, e.g. using a command

python3 taskgain.py

or similarly with your interpreter name and possibly replacing taskgain with activetask.

You should see output similar to this:

* Serving Flask app 'taskgain'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit

Notice the port number 5000 on the second-to-last line. It might not be 5000 for you, but you need to know it.

Now, open a browser and visit http://localhost:5000/, replacing 5000 with the port number as needed.

You should see a fronty page which lets you enter a username (and which directs you to that user's task list.) Try logging in, modifying tasks, and making a new task. (You'll need to manually enter the URL localhost:5000/task/new/ to make a new task.)

2. New features

Modify the sample application to add these new features. Test them to make sure they work.

A. Single task view

Make a new route /task/<taskid>/ that does the following:

  • Performs a DB query to get data about the task with id taskid
  • If this query fails, returns a 400 Bad Request error
  • If the query succeeds, it renders a template called task_view.html that you create in the templates/ subdirectory which displays a page listing all the information about that task in a nice format (e.g. with labels for the different fields and proper formatting for the dates/times)
  • In that page, any time a username is displayed, it is actually a link to that user's task list view.

Then, modify the /task/new/submit route so that when a new task is created, the redirect goes to the single task view page for the newly-created task. To do this, you'll need to know this neat trick: The query

SELECT last_insert_rowid();

will return the primary key of the most recently inserted row. So calling this immediately after an SQL INSERT is the proper way to find the unique identifier of the added row.

B. On this day

Here's a function that can take a day described by its year, month, and day numbers and return two time stamps ts0,ts1 so that a timestamp x lies within that day if and only if ts0 <= x < ts1.

In [ ]:
import datetime

def timestamp_range_for_day(year,month,day):
    """
    Return the timestamps when a calendar day
    begins and ends.
    """
    ts0 = datetime.datetime(year,month,day).timestamp()
    ts1 = (datetime.datetime(year,month,day)+datetime.timedelta(days=1)).timestamp()
    return ts0,ts1

Use this to add the following feature to the task list management application: Visiting a URL of the form /reports/day/2024/04/09/ will show a page with two sections:

  • Tasks created on that day
  • Tasks that were last updated on that day

Each section should contain a list of tasks with the described property.

As with the previous feature, this one should use a new template. It is recommended to base your work on the task list view template, since that one also involves a task list.

3. Custom sorts and max/min

Use anonymous functions (lambda) with Python's sorted(), max(), or min() functions to answer these questions.

A.

Generate the first 20 powers of 7 (meaning $7^1$ to $7^{20}$) and sort them according to how many different decimal digits they use. That is, 343 would appear near the start of the list since it uses only two distinct digits, while 1628413597910449 would appear near the end, as it uses all 10 digits.

B.

Here's a text file with 10000 English words, one per line:

Let's say the endscore of a word is the number of times its last letter appears in the word. For example, "plasma" has an endscore of 2 because the last letter, a, appears twice. And "associates" has an endscope of 3 because it contains 3 copies of the last letter, s.

Using custom sorting and lambda, find 20 words with the highest endscores in this list.

C.

Use the same word list as the last problem. Suppose we say the variety of a word is the ratio of the number of distinct letters to the length of the word. For example, "cameras" has 6 distinct letters and has a length of 7, so its variety is $\frac67 \approx 0.85714$.

Among words with at least four letters, find one that has the lowest variety.

Revision history

  • 2024-04-07 Initial release