CSAir

.idea
    .name 13 B
    Assignment2.0.iml 295 B
    dictionaries
       lantay77.xml 357 B
    encodings.xml 171 B
    misc.xml 348 B
    modules.xml 289 B
    runConfigurations
       Server.xml 1008 B
       Unittests_in_Tests.xml 1 KB
    scopes
       scope_settings.xml 143 B
    vcs.xml 189 B
    workspace.xml 59 KB
CSAir.py 11 KB
CSAir_helpers.py 9 KB
CSAir_json.py 7 KB
CSAir_server.py 5 KB
Graph
    DiGraph.py 9 KB
    Edge.py 518 B
    Node.py 360 B
Location.py 1 KB
ManualTestPlan.odt 441 KB
ManualTestPlan.pdf 1029 KB
Query.py 2 KB
README 499 B
Server.py 8 KB
Tests
    expected
       brief_print_expected.txt 13 B
       continents_expected.txt 58 B
       expected.json 1 KB
       hubs_expected.txt 70 B
       list_expected.txt 28 B
       longest_expected.txt 36 B
       other_expected.txt 205 B
       print_expected.txt 130 B
       shortest_expected.txt 37 B
    invalid.json 15 KB
    out
       brief_print_test.txt 13 B
       continents_test.txt 58 B
       hubs_test.txt 70 B
       list_test.txt 28 B
       longest_test.txt 36 B
       other_test.txt 205 B
       out.json 1 KB
       print_test.txt 130 B
       shortest_test.txt 37 B
    testCSAir.py 3 KB
    testFunctionsForServer.py 1 KB
    testGraph.py 1 KB
    testLocation.py 938 B
    testServer.py 6 KB
    test_2.1.py 8 KB
    valid.json 871 B
    valid2.json 582 B
add_city_post.py 800 B
changes 633 B
cmi_hub.json 1 KB
map_data.json 15 KB
map_data_r2.json 15 KB
static
    bootstrap.js 59 KB
    css
       bootstrap-theme.css 20 KB
       bootstrap-theme.css.map 22 KB
       bootstrap-theme.min.css 18 KB
       bootstrap.css 129 KB
       bootstrap.css.map 215 KB
       bootstrap.min.css 106 KB
       starter-template.css 186 B
    fonts
       glyphicons-halflings-regular.eot 19 KB
       glyphicons-halflings-regular.svg 61 KB
       glyphicons-halflings-regular.ttf 40 KB
       glyphicons-halflings-regular.woff 22 KB
    js
       bootstrap.js 59 KB
       bootstrap.min.js 31 KB
templates
    city.html 13 KB
    routes.html 10 KB
uploads
Server.py
from CSAir_server import *
import os
from flask import Flask, render_template, request, redirect
from werkzeug import utils
app = Flask(__name__)  # Initialize the Flask application
app.config['UPLOAD_FOLDER'] = 'uploads/'  # This is the path to the upload directory
app.config['ALLOWED_EXTENSIONS'] = set(['json'])  # These are the extension that we are accepting to be uploaded


# For a given file, return whether it's an allowed type or not
def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1] in app.config['ALLOWED_EXTENSIONS']

log = ServerLog()
route_log = ServerLog()
route_stats = {}


@app.route('/')
def display_main():
    """
    Display the home page/cities page
    :return: the home page/cities page
    """
    try:
        code = request.args.get('code').upper()
    except AttributeError:
        code = None

    rm = request.args.get('rm')
    if rm is not None:  # remove a node.
        if graph.remove_node(rm):
            log.log_yellow(rm + " successfully removed.")

    s_text = get_stats(graph)  # get overall stats.
    city_menu = generate_city_menu(graph)  # generate the city menu
    h_text = n_to_br(print_hubs(graph))  # get hubs info
    c_text = n_to_br(print_continents(graph))  # get continents info

    #set city params to none for HTML rendering
    c_info, continent, country, latitude, longitude, name, pop, region, timezone, wx_url = set_city_params_to_none()
    if code is not None:  # if city exists, get city info.
        c_info = n_to_br(lookup(graph, code))
        city_node = graph.find_node(code)
        if city_node is None:
            log.log_yellow(code + " does not exist.")
            return redirect("/")
        current_city = city_node.get_object()

        name = current_city.name
        country = current_city.country
        continent = current_city.continent
        timezone = current_city.timezone
        latitude = current_city.latitude
        longitude = current_city.longitude
        pop = current_city.population
        region = current_city.region
        if country == "US" or country == "USA":  # Add weather button if the city is in the US
            wx_url = 'http://aviationweather.gov/adds/metars/index.php?submit=1&station_ids=K' + code \
                     + '&chk_metars=on&hoursStr=2&std_trans=translated&chk_tafs=on'

    #render the HTML and return.
    return render_template('city.html', cities=sorted(graph.get_nodes()), map_url=generate_map_url(graph),
                           city_menu=city_menu, c_info=c_info, s_info=s_text, code=code, log=log.get_log(), hubs=h_text,
                           conts=c_text, WX_url=wx_url, country=country, name=name, continent=continent,
                           timezone=timezone, latitude=latitude, longitude=longitude, pop=pop, region=region)


@app.route('/<path:fname>')
def display_static(fname):
    """
    Static route to send CSS and JS.
    :param fname: requested filename
    :return: the file
    """
    #send_static_file will guess the correct MIME type
    return app.send_static_file(fname)


@app.route('/routes')
def display_routes():
    """
    Display the routes page
    :return: routes page
    """
    add, clear, dest, direction, distance, noquery, rm, route_str, source = get_route_args(request)
    if clear == "routes":  # clear route query history
        route_log.clear()

    if add is not None:  # add new route.
        if add_route_helper(graph, source, dest, distance, direction):
            log.log_green("Successfully added route: " + source + " to " + dest)
        else:
            log.log_yellow("Unable to add route: " + source + " to " + dest)

        route_str = source + "-" + dest  # set route string to display new route.

    elif rm is not None:  # remove route.
        if remove_route_helper(graph, source, dest, direction):
            log.log_green("Successfully removed route: " + source + " to " + dest)
        else:
            log.log_yellow("Unable to remove route: " + source + " to " + dest)

    route = generate_shortest_route(graph, source, dest, rm, add, log)  # generate list of nodes in the route.

    if route is None:  # If we did not find shortest route, assume they specified a manual route
        route = generate_route_list(route_str)
    else:  # Otherwise, generate the route string for the log.
        route_str = generate_route_string(route)

    url_string = generate_map_url_from_list(graph, route)

    #finish the url string and create log string.
    if route_str is not None:
        log_string = '<a href="/routes?route=' + route_str + '&noquery=y">' + route_str + "</a><br>"
        if noquery is None:
            route_log.append(log_string)

    #get route statistics
    route_stats_str = ""
    if route is not None:
        route_stats_str = n_to_br(route_helper(graph, route))

        if "Error" in route_stats_str:
            url_string = generate_map_url(graph)
            log.log_yellow("Did not find route: " + route_str)

    city_menu = generate_city_menu(graph)
    return render_template('routes.html', cities=sorted(graph.get_nodes()), map_url=url_string, city_menu=city_menu, log=log.get_log(), route_log=route_log.get_log(), r_info=route_stats_str)


@app.route('/save.json')
def export_json():
    save_json(graph, "static\save.json")
    return app.send_static_file("save.json")


@app.route('/upload', methods=['POST'])
def upload():
    """
    Route that will process the file upload
    Adapted from: http://flask.pocoo.org/docs/0.10/patterns/fileuploads/
    and http://runnable.com/UiPcaBXaxGNYAAAL/how-to-upload-a-file-to-the-server-in-flask-for-python
    :return:
    """
    # Get the name of the uploaded file
    file = request.files['file']
    # Check if the file is one of the allowed types/extensions
    if file and allowed_file(file.filename):
        # Make the filename safe, remove unsupported chars
        filename = utils.secure_filename(file.filename)
        # Move the file form the temporal folder to
        # the upload folder we setup
        file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
        # Redirect the user to the uploaded_file route, which
        # will basically show on the browser the uploaded file
        log.log_green("Successfully uploaded " + filename)

        if merge_json(graph, "uploads/" + filename):
            log.log_green("Successfully merged data.")
        else:
            log.log_yellow("Failed to merge data.")

    else:
        log.log_yellow("Failed to upload " + file.filename)

    return redirect('/')


@app.route('/add_city')
def add_city():
    """
    Handle the Add city form request.
    :return: The city page or Home page if city was not added.
    """
    try:
        code = request.args.get('cityCode').upper()
    except AttributeError:
        code = None

    api = request.args.get('api')
    edit = request.args.get('edit')
    if edit == "true":
        print("Edit is true!")
        old_code = request.args.get('old_code')
        node = graph.find_node(old_code)
        graph.remove_node(node, False)

    #add city from Wunderground API
    if api == "true" and code is not None:
        if json_api_request(graph, code) is True:
            return_string = code + " successfully added from Wunderground API."
        else:
            return_string = "Error: Unable to add " + code + " from API."

    else:  # otherwise get manual arguments.
        continent, country, latitude, longitude, name, population, region, timezone = get_add_city_args(request)

        return_string = add_city_helper(graph, code, name, country, continent,
                                        timezone, latitude, longitude, population, region)

    if "Error" in return_string:
            #if modifying the city failed, add the old one back to the graph.
            log.log_yellow(return_string)
            if edit == "true":
                graph.add_node(node.get_object(), node)
                log.log_yellow("Editing " + code + " failed:")
    else:
            #edit current routes to match new information!
            log.log_green(return_string)
            if edit == "true":
                update_routes(graph, code, old_code)
                log.log_green("Editing " + code + " succeeded:")
            return redirect('/?code=' + code)

    return redirect('/')

graph = load_initial_json(False)
#app.run(debug=True)
app.run()