Python server with Flask

With Flask and SQLAlchemy I talked about in the last post, I was able to implement a python server. It is able to show a list of restaurants in the main page. Clicking on restaurant names show their menu, and each menu item can be edited or deleted. Users can also create new menu items. The database uses SQLAlchemy, and url resolving and HTTP requests handling use Flask, a microframework that makes implementations of web servers very easy.

The link to the project on GitHub is here.

With flask, resolving url addresses is simply app.route('format'), and under this line declare the method for this address. Here is an example:

This means whenever the address fits the format host/restaurants/int, the method restaurantMenu will be executed. restaurant_id is a variable extracted from the url and passed in the method as a parameter. Whatever this method returns shows up on the webpage. In this case, the method is returning the result of render_templaterender_template is a method in Flask that looks for the template specified in the first parameter in /templates and pass in necessary variables. menu.html looks like this:Screen Shot 2016-01-13 at 9.40.55 AM

items is the variable passed in this template. Here html execution arguments are used.

url_for is another tool used in this project. It is also included in Flask. The first parameter is the handler method of the product url, and other parameters are variables passed.

The next step is for methods to handle both GET and POST HTTP methods. Here’s how to do it:

methods need to be put in @app.route. Of course, request class also needs to be imported from Flask. Handling different kinds of methods is virtually the same as handling one. It’s only one if statement away.

Finally, for the server to repond to requests with JSON object, objects in the database need to have a function that returns all of their information.

In object class of the database setup python file:

And then use jsonify class provided by Flask to return json:
return jsonify(MenuItem = menuItem.serialize)
The json can then be used by any kind of application!

As a next step of this project, I plan to implement a server that works with iOS applications. I may need to write a framework for Swift to talk with my server. This means a lot of work, but it has great potential!

I’ll just forget about the fact that I have a midterm 30 minutes later and one more tomorrow.

Progress of Wheeshare

Wheeshare has finally achieved all of its necessary functionalities. Before it could provide functions such as request, approve request and lend, but it was impossible for user to “step back” from the relationships with cancel request or re-lend item. Now users are able to cancel their requests and owners of items can re-lend their stuff once they have them back from the last borrowers. Besides this breaking relationship improvement, users can now view the status of their items in the main table view, such as “lended to Bill” or “requested by Jason”.

The logic of the relationship is pretty efficient. I used a little bit of binary spirit while designing it. Each item has three variables relevant to the borrow-lend relationship: giver, requester, and connected. Among these three, giver and requester are of type PFUser (user class written by Parse, which tragically is going to close in one year, fml), and connected is a Bool. Giver for an item is the owner and cannot be changed for the lifespan of the item. Whenever a user requests an item, the requester variable of the item will be given the value of this user. Connected means if the relationship is successfully built. If the owner presses “approve request”, connected will be changed to true.

Therefore, two free variables produce three possible outcomes:

  1. requester is not null and connected is false. The item is currently available and no one has requested.
  2. requester is someone and connected is false. The item is requested but not approved yet.
  3. requester is someone and connected is true. The item is in a borrow-lend relationship.

requester is null && connected is true cannot happen because that doesn’t make any sense.

As for deleting the items, owners are not allowed to delete their items on the platform if the items are requested or in a relationship. They are prompted to take care of the requests.

Things to do: improve UI HARD. If I knew I would be developing iOS apps, I would have gone to some art clubs back in high school. Switch to another online database or write one by myself with php and SQL. The latter would be challenging but also very rewarding.

The other day I discovered an app called PartiO, which aims at exactly the same thing as my app – let students share their stuff. The only difference is that they let people share with profits. I have already contacted them and wish to help them improve the product. Hopefully we will achieve something together.

OK these last two paragraphs just made me add “Babbles” to the category of this post.

Thoughts about building an SMS system

What a sunny day. Yesterday I decided to take one more class – Math221 to discover the possibility of math majoring. I don’t know if it’s possible for me to triple major in CS, ECE and math but we’ll see.

Recently I’ve been thinking how I can improve my Wheeshare app. I believe protecting user privacy should be of high priority, so the app could be better with a built-in SMS system like Taobao’s Aliwangwang or WeChat. However building such thing is no easy – from the data structure of chats to UI design to speed enhancement. No one wants a chat screen that lags. I have to think of an efficient architecture. If everything goes perfectly, I will upload the project to GitHub for others to use.

For the chat screen, I plan to use a UITableView to hold every chat message, with user thumbnail profile picture on each side. I will make a NIB file for the chat bubble and add a UILabel in it to display chat. One technical challenge would be how to update messages if the user received a new one. I will look into Parse API documentation to look for a notification API so that my app can observe the database on the user’s phone.

As for the general structure, I would like to create and store an object for each pair of users (if they started chatting, of course) and label it with two users’ IDs. When the app inits it tries to retrieve chats from online database with the current user ID. Inside each object I store an array of chat messages, each labeled with its sender.

Another technical challenge: how to cache all messages locally? For now, my tentative solution is to use CoreData so that I can directly push any updated chat object into the Core Data Stack. It sounds so simple right now but I am 100% sure it will give me a headache when I try to implement it.

One other problem to think about is whether to keep the connection between two users after they ended their relationship as borrower/lender. Again this is a privacy issue that I need to think about.

Other than this SMS system plan, I need to somehow restrict the app’s area. I probably need to get users’ locations and limit the access to Duke University for now to prevent possible malicious data attack. Thank you for watching, that’s it for today.

Paging view with control

Before talking about boring(no it’s absolutely not) programming, some babbles about my life. I’m going back to America tomorrow and will arrive at midnight. Let’s hope I won’t get much jet lag. As for the semester, I kind of need to learn to drive and get a license so life won’t suck. I’m taking a pretty hard algorithm class and at the same time having two jobs so wish me luck!

In the project StoreSearch, I used scroll view and UIPageControl to implement a paging view with control once, but what did I know I just mindlessly followed the detailed tutorial. Thankfully, I used the money granted by Duke CoLab to subscribe for online tutorials on Ray Wenderlich’s website and learned again about paging view there.

There are two ways to do this: one is using UIScrollView and set constraints on pages manually, the other is taking advantage of UIPageViewController and have things set up. I personally prefer the former because it’s more customizable, so selfishly I’ll write about that here.

First, we should have a view controller set up. This controller takes care of each page in our paging view. Then in the initial view controller put in a UIScrollViewController and set proper constraints.

Screen Shot 2016-01-09 at 8.20.46 PM

Next we accomplish paging through the following steps:

  1. set pagingEnabled to true:
    scrollView.pagingEnabled = true
  2. keep view controllers in a dictionary so that we can set constraints later:
    pages = [page1, page2, page3, page4, page5]
            let views = ["view": view, "page1": page1.view, "page2": page2.view, "page3": page3.view, "page4": page4.view, "page5": page5.view]
    /*"pageX" means the Xth view controller.*/
  3. set constraints on views:
    let metrics = ["edgeMargin": 10, "betweenMargin": 20]
    
    let verticalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("V:|[page1(==view)]|", options: [], metrics: nil, views: views)
    NSLayoutConstraint.activateConstraints(verticalConstraints)
            
    let horizontalConstraints =
        NSLayoutConstraint.constraintsWithVisualFormat("H:|-edgeMargin-[page1(==view)]-betweenMargin-[page2(==view)]-betweenMargin-[page3(==view)]-betweenMargin-[page4(==view)]-betweenMargin-[page5(==view)]-edgeMargin-|", options: [.AlignAllTop, .AlignAllBottom], metrics: metrics, views: views)
    
    NSLayoutConstraint.activateConstraints(horizontalConstraints)

Oh, before all these remember to set the view controllers for each page not to autoresize:

view.translatesAutoresizingMaskIntoConstraints = false

And voila we have a nice looking five pages view.

To add a page control, first add it in storyboard and set proper constraints and outlet:

Screen Shot 2016-01-09 at 8.21.30 PM

Then follow the steps below:

  1. set its number of pages:
    pageControl.numberOfPages = pages.count
  2. show the correct current page. We need to round the value of offset.x/width because we would like it to show the correct page when we are in between pages:
    extension TutorialViewController: UIScrollViewDelegate {
        func scrollViewDidScroll(scrollView: UIScrollView) {
            let pageWidth = CGRectGetWidth(scrollView.bounds)
            let pageFraction = scrollView.contentOffset.x / pageWidth
            pageControl.currentPage = Int(round(pageFraction))
        }
    }
  3. control the change of page with an action outlet:
    @IBAction func pageChanged(sender: AnyObject) {
            let currentPage = sender.currentPage
            let pageWidth = CGRectGetWidth(scrollView.bounds)
            let targetContentOffsetX = CGFloat(currentPage) * pageWidth
            
            UIView.animateWithDuration(0.33, delay: 0,
                options: .CurveEaseInOut, animations: { () -> Void in
                    self.scrollView.contentOffset.x = targetContentOffsetX
                }, completion: nil)
        }

    Here we’re using a cute little animation.

And there we go! Paging view with control. I uploaded the code to GitHub in case I need the template in future development. If one intends to use it be aware of its license.

Dynamic Programming – Knapsack & Shortest Path

Happy New Year! I sure enjoyed my holiday. I visited my girlfriend’s city in southern China and spent happy three days with her :).

These two days I read about dynamic programming. This is the first time I ever systematically learn its principles, so I thought I should write my thoughts down.

When to use dynamic programming? In my opinion, when the problem fits the following requirements:

  1. It can be divided into a certain amount of subproblems.
  2. The subproblems can be solved in a certain order.
  3. There are not too many variables.

“Dynamic programming” is really a fancy phrase of solving problems in an order. I think it essentially is recursion with memoization. I’ll write solutions of two sample problems here. One is the famous knapsack program, the other is finding the shortest path in a graph with negative edges.

Knapsack problem: Given a “bag” that can only hold items weighing less than or equal to W and weights w and values v of n items, how should we pick the items so that we have the largest possible value in the “bag”?

Here we have two variables with which we divide the problem: the number of items we are choosing from and the largest weight we can have. We use these two variables because when they are small, the problem is trivial: when we can only choose from 1 item, we have to choose that one; when the weight available is small, we can only choose from “light” items. Another reason is that we can solve subproblems in an order: from a small number of items to the whole group, and from 0 weight to W. It is mandatory that we understand the spirit of dynamic programming, because we use it to divide subproblems.

Now we consider if we choose an item or not. Assume we are looking for the largest possible value for i items and weight t – OPT(i, t) (OPT stands for “optimal”, not optional practical training lol). If the optimal plan includes item i, then OPT(i, t) = OPT(i – 1, t – Wi) + Vi. If it does not, OPT(i, t) = OPT(i – 1, t). When t is less than Wi, it can only be the latter. In this way, we have our recurrence function:

OPT(i, t) = MAX(OPT(i- 1, t – Wi) + Vi, OPT(i – 1, t))

The rest is easy.

Shortest Path Problem: In a graph with negative edges but without negative cycles, find the shortest path from vertex s to t.

(I should note here that MacBook keyboard sucks. It feels so bad.)

We use OPT(i, v) to represent the least weight from vertex v to t, with at most i edges. If the optimal path P contains at most i – 1 edges, OPT(i, v) = OPT(i – 1, v). If P contains i edges, OPT(i, v) = OPT(i – 1, w) + cost(v to w).

Therefore, OPT(i, v) = MIN(OPT(i – 1, v), OPT(i – 1, w) + cost(v to w))

To be honest, I don’t quite understand how this works. I can see it does the job but I can’t form a logical shortcut of the algorithm in my mind. Anyway, I think with practice I will be able to master dynamic programming.

So I came back to this server again…

I used to build my personal website on this server with handwritten html and css. Later I found out it is better to use WordPress. After all I hate calculating pixels and designing layout. WordPress helps me with all that.

I requested a VM from Duke OIT and installed WordPress there. I wrote a few Tech blogs about iOS and just when I thought I could use the service forever and ever, I could no longer access my VM. I don’t know if that’s because I’m back in China but even with VPN I am unable to get on.

Enough said, I came back. I spent some time this morning installing WordPress and I am planning to write here. I’m sharing this server with two of my best friends and talented computer scientists so security is not a problem.

Off we go.