code: import requests, json, populartimes
  import numpy as np
  import pandas as pd
  from itsdangerous import URLSafeTimedSerializer, SignatureExpired
  from form import DetailForm, UserForm, UserLogin, NGOForm
  from sqlalchemy import create_engine
  from sqlalchemy.orm import scoped_session, sessionmaker
  from datetime import datetime, timedelta
  from flask import Flask, redirect, url_for, request, render_template, session, flash
  from flask_mail import Mail, Message
  from models import get_coords
  from flask_login import LoginManager, login_required
  from flask_googlemaps import GoogleMaps, Map
  from haversine import haversine
  
  # Create Flask App
  app = Flask(__name__)
  app.secret_key = "xb1\x058\xb8o\x82\xaf\xdb\xd5I"
  app.config.from_pyfile('config.cfg')
  
  # Get Google Places API: https://developers.google.com/places/web-service/get-api-key and replace
  MyAPI_key = "Put your key"
  
  GoogleMaps(app,key=MyAPI_key)
  mail = Mail(app)
  
  key = 'xb1\x058\xb8o\x82\xaf\xdb\xd5I'
  engine = create_engine("mysql+pymysql://root:pawan@localhost/covid")
  db = scoped_session(sessionmaker(bind=engine))
  s = URLSafeTimedSerializer(key)
  
  login_manager = LoginManager()
  login_manager.init_app(app)
  login_manager.login_view = "userlogin"
  
  # URL for request to google place text search to find user address based on what is typed in
  url = "https://maps.googleapis.com/maps/api/place/textsearch/json?"
  
  # constant factor used later to calculate the area (longitude, latitude) to scan for stores
  alpha = 180/(np.pi*6371000)
  
  @app.route('/')
  def home():
      return render_template('homes.html')
  
  
  @app.route("/userregister", methods=["GET", "POST"])
  def register():
      form = UserForm(request.form)
      if request.method == 'POST' and form.validate():
          fname = form.fname.data
          lname = form.lname.data
          email = form.email.data
          password = form.password.data
          confirm = form.confirm_password.data
  
          # ipaddr = request.environ.get('HTTP_X_REAL_IP', request.remote_addr)
          # loc = get_coords(ipaddr)
  
          ipaddr = '157.37.154.227' # hard coded till we deploy it
          loc = get_coords(ipaddr)
          lat, lon = loc[0], loc[1]
  
          emaildata = db.execute("SELECT email FROM users WHERE email=:email", {"email": email}).fetchone()
  
          if emaildata is not None:
              flash("Email taken", "danger")
              return render_template("userregister.html", form=form)
  
          if password == confirm:
              db.execute("INSERT INTO users (first_name, last_name, email, pass,lon, lat) VALUES (:fname, :lname, :email, :password, :lon,:lan)", {
                         "fname": fname, "lname": lname, "email": email, "password": password, "lon":lon, "lat":lat})
              db.commit()
  
              email = request.form['email']
              token = s.dumps(email, salt='email-confirm')
  
              msg = Message('Confirm Email', sender='anhappysingh@gmail.com', recipients=[email])
              link = url_for('confirm_email', token=token, _external=True)
  
              msg.body = link
              mail.send(msg)
              flash("A confirmation email has been sent. Please confirm your email.", "success")
              return render_template("userregister.html", form=form)
  
          else:
              flash("Passwords do not match", "danger")
              return render_template("userregister.html",form=form)
  
      return render_template("userregister.html",form=form)
  
  
  @app.route("/ngoregister", methods=["GET","POST"])
  def ngoregister():
      form = NGOForm(request.form)
      if request.method == 'POST' and form.validate():
          name = form.name.data
          email = form.email.data
          password = form.password.data
          confirm = form.confirm_password.data
  
          # ipaddr = request.environ.get('HTTP_X_REAL_IP', request.remote_addr)
          # loc = get_coords(ipaddr)
  
          ipaddr = '157.37.154.227'  # hard coded till we deploy it
          loc = get_coords(ipaddr)
          lat, lon = loc[0], loc[1]
  
          emaildata = db.execute("SELECT email FROM users WHERE email=:email", {"email": email}).fetchone()
  
          if emaildata is not None:
              flash("Email taken", "danger")
              return render_template("ngoregister.html", form=form)
  
  
          if password == confirm:
              db.execute("INSERT INTO users (first_name, email, pass, usertype ,lon, lat) VALUES (:fname, :email, :password, :usertype, :lon,:lat)",
                         { "fname": name, "email": email, "password": password, "usertype":3, "lon":lon, "lat":lat})
              db.commit()
  
              email = request.form['email']
              token = s.dumps(email, salt='email-confirm')
  
              msg = Message('Confirm Email', sender='anhappysingh@gmail.com', recipients=[email])
              link = url_for('confirm_email', token=token, _external=True)
  
              msg.body = link
              mail.send(msg)
              flash("A confirmation email has been sent. Please confirm your email.", "success")
              return render_template("ngoregister.html", form=form)
  
          else:
              flash("Passwords do not match", "danger")
              return render_template("ngoregister.html",form=form)
  
      return render_template("ngoregister.html",form=form)
  
  @app.route('/confirm_email/<token>')
  def confirm_email(token):
      try:
          email = s.loads(token, salt='email-confirm', max_age=36000)
          flash("You are registered. Please login", "success")
          return redirect(url_for('userlogin'))
      except SignatureExpired:
          flash("The link has expired. Please login", "danger")
          return render_template("userregister.html")
  
  
  @app.route("/userlogin", methods=["GET", "POST"])
  def userlogin():
      form = UserLogin(request.form)
      if request.method == 'POST' and form.validate():
  
          email = request.form.get("email")
          password = request.form.get("password")
  
          emaildata = db.execute("SELECT email FROM users WHERE email=:email", {"email": email}).fetchone()
          passwordData = db.execute("SELECT pass FROM users WHERE email=:email", {"email": email}).fetchone()
          userTypeData = db.execute("SELECT userType FROM users WHERE email=:email", {"email": email}).fetchone()
  
          if emaildata is None:
              flash("Email not found. Please try again.", "danger")
              return render_template("userlogin.html", form=form)
          else:
  
              for password_data in passwordData:
                  if password==password_data:
                      session["log"] = True
                      flash("You are logged in.")
                      session["USER"] = email
  
                      print(userTypeData.userType)
  
                      if (int(userTypeData.userType)==2):
                          print("yes")
                          return redirect(url_for('userhome'))
                      elif (int(userTypeData.userType)==3):
                          return redirect(url_for('ngohome'))
                  else:
                      flash("Incorrect password", "danger")
                      return render_template("userlogin.html",form=form)
      return render_template("userlogin.html",form=form)
  
  
  @app.route("/forgetpassword", methods=["GET", "POST"])
  def forget_password():
      if request.form.get("email"):
          email = request.form['email']
          emaildata = db.execute("SELECT email FROM users WHERE email=:email", {"email": email}).fetchone()
  
          if emaildata is None:
              flash("Email not found. Please try again.", "danger")
              return render_template("forgetpassword.html")
          else:
              new_password = (str('new_password'))
              db.execute("UPDATE users SET pass=:password WHERE email=:email", {"password": new_password, "email": email})
              db.commit()
              msg = Message('Forget Password',
                            sender='anhappysingh@gmail.com', recipients=[email])
              msg.body = 'Your new password is: new_password'
  
              mail.send(msg)
              flash("Your password was sent to your email.", "success")
              return redirect(url_for('userlogin'))
      return render_template("forgetpassword.html")
  
  
  @app.route("/logout")
  @login_required
  def logout():
      session.clear()
      flash("You are logged out", "success")
      return redirect(url_for('userlogin'))
  
  @app.errorhandler(401)
  def page_not_found(e):
      return render_template('error.html')
  
  @app.route('/error')
  def error():
      return render_template('error.html')
  
  
  @app.route('/stop')
  def stop():
      return render_template('stop.html')
  
  
  @app.route("/admin")
  def admin():
      return render_template("adminlogin.html")
  
  
  def get_map(loc):
      mymap = Map(identifier="view-side", lat=loc[0], lng=loc[1],
          markers=[{
              'icon': 'http://maps.google.com/mapfiles/ms/icons/blue-dot.png','zoom': 16,
              'lat': loc[0], 'lng': loc[1], 'infobox': "<b>Your current location</b>",
          'style':'width:500px'}])
  
      return mymap
  
  
  @app.route("/ngohome", methods=['GET','POST'])
  def ngohome():
      # Hardcoded till we deploy it so that we can get user ip addr
      ipaddr = '157.37.154.227'
      loc = get_coords(ipaddr)
  
      # hardcoded can be taken by nearest requesters
      loc2 = [26.9363461, 75.9213346]
      mymap = get_map(loc)
  
      calc_dist = haversine(loc,loc2)
      if calc_dist<20:
          print("yes there is a request")
  
      return render_template("ngohome.html", mymap=mymap)
  
  
  @app.route("/userhome", methods=['GET','POST'])
  def userhome():
  
      # Hardcoded till we deploy it so that we can get user ip addr
      ipaddr = '157.37.154.227'
      loc = get_coords(ipaddr)
      mymap = get_map(loc)
  
      if request.form.get("packets"):
          packets = request.form['packets']
          email = session["USER"]
          current = db.execute("SELECT quantity FROM users WHERE email=:email", {"email": email}).fetchone()
  
          if int(packets) < 1:
              flash("Invalid Quantity", "danger")
              return redirect(url_for('userhome'))
          if int(packets) > 6:
              flash("Maximum 6 from one signup", "danger")
              return redirect(url_for('userhome'))
          if int(current.quantity) != 0:
              flash("You already submitted a request","danger")
              return redirect(url_for('userhome'))
  
          else:
              db.execute("UPDATE users SET quantity=:quantity WHERE email=:email", {"quantity": packets, "email": email})
              db.commit()
  
              flash("Your Request has been submitted", "success")
              return redirect(url_for('userhome'))
  
      # ipaddr = request.environ.get('HTTP_X_REAL_IP', request.remote_addr)
      # loc = get_coords(ipaddr)
      return render_template("userhome.html", mymap= mymap)
  
  
  # Run Store Search and Selection
  @app.route('/details', methods=['GET', 'POST'])
  def detail():
      form = DetailForm(request.form)
      if request.method == 'POST' and form.validate():
          # Import User Input
          user_address = form.user_address.data
          store_type = form.store_type.data
          radius = form.radius.data 
  
          radius = int(radius)
          
          # Find the google place from the user_address input
          user_address_res = requests.get(url + 'query=' + user_address + '&key=' + MyAPI_key)
          x = user_address_res.json()
  
          user_location = x["results"][0]["geometry"]["location"]
  
          user_latitude = user_location["lat"]
          user_longitude = user_location["lng"]
          
          # Define search area around the user location
          delta = radius*alpha
  
          p1 = (user_latitude-delta, user_longitude-delta)
          p2 = (user_latitude+delta, user_longitude+delta)
  
          if store_type == 'supermarket':
              results = populartimes.get(MyAPI_key, ["grocery_or_supermarket"], p1, p2, radius=radius, all_places=False, n_threads=1)
          
          if store_type == 'pharmacy':
              results = populartimes.get(MyAPI_key, ["pharmacy"], p1, p2, radius=radius, all_places=False, n_threads=10)
  
          # Find out the current time at the user's location (can only be found by a place details request)
          user_location_id = x["results"][0]["reference"]
  
          url_details = "https://maps.googleapis.com/maps/api/place/details/json?"
          user_location_details_res = requests.get(url_details+"key="+MyAPI_key+"&place_id=" + user_location_id)
          y = user_location_details_res.json()
  
          utc_offset = y["result"]["utc_offset"]
          time_now = datetime.utcnow()+timedelta(hours=utc_offset/60)
          
          # Create a list of stores with their activity data (current if available, otherwise average at current time)
          # Closed stores (activity=0) are omitted
          store_list = []
  
          for item in results:
              if "current_popularity" in item:
                  store_list.append([item["current_popularity"], item["name"], item["id"]])
              else:
                  temp = item["populartimes"][time_now.weekday()]["data"][time_now.hour]
                  if temp != 0:
                      store_list.append([temp, item["name"], item["id"]])
          
          # If no Stores are found give out an error
          if len(store_list) == 0:
              # return 'there has been an error: No data available for this choice'
              return redirect(url_for('error'))
          
          # Select the store with the least activity and get its ID and name
          df = pd.DataFrame(store_list)
          store_place_id = df.iloc[df[0].idxmin(), 2]
          store_name = df.iloc[df[0].idxmin(), 1]
          
          # Create google maps link based of store_place_id
          store_gmap_url = "https://www.google.com/maps/place/?q=place_id:" + store_place_id
  
          return render_template('stop.html', value=store_name, key=store_gmap_url)
  
      else:
          return render_template('details.html', form=form)
  
  
  @login_manager.user_loader
  def load_user(userid):
      return db.query.get(userid)
  
  
  if __name__ == '__main__':
      app.config['TEMPLATES_AUTO_RELOAD'] = True
      app.run(debug=True)
  
apis: pandas.DataFrame