Example #1
0
def get_elevations_for_flight(flight):
    cached_elevations = cache.get("elevations_" + flight.__repr__())
    if cached_elevations:
        return cached_elevations

    """
    WITH src AS
        (SELECT ST_DumpPoints(flights.locations) AS location,
                flights.timestamps AS timestamps,
                flights.locations AS locations
        FROM flights
        WHERE flights.id = 30000)
    SELECT timestamps[(src.location).path[1]] AS timestamp,
           ST_Value(elevations.rast, (src.location).geom) AS elevation
    FROM elevations, src
    WHERE src.locations && elevations.rast AND (src.location).geom && elevations.rast;
    """

    # Prepare column expressions
    location = Flight.locations.ST_DumpPoints()

    # Prepare cte
    cte = (
        db.session.query(
            location.label("location"), Flight.locations.label("locations"), Flight.timestamps.label("timestamps")
        )
        .filter(Flight.id == flight.id)
        .cte()
    )

    # Prepare column expressions
    timestamp = literal_column("timestamps[(location).path[1]]")
    elevation = Elevation.rast.ST_Value(cte.c.location.geom)

    # Prepare main query
    q = (
        db.session.query(timestamp.label("timestamp"), elevation.label("elevation"))
        .filter(and_(cte.c.locations.intersects(Elevation.rast), cte.c.location.geom.intersects(Elevation.rast)))
        .all()
    )

    if len(q) == 0:
        return []

    start_time = q[0][0]
    start_midnight = start_time.replace(hour=0, minute=0, second=0, microsecond=0)

    elevations = []
    for time, elevation in q:
        if elevation is None:
            continue

        time_delta = time - start_midnight
        time = time_delta.days * 86400 + time_delta.seconds

        elevations.append((time, elevation))

    cache.set("elevations_" + flight.__repr__(), elevations, timeout=3600 * 24)

    return elevations
Example #2
0
def get_elevations_for_flight(flight):
    cached_elevations = cache.get('elevations_' + flight.__repr__())
    if cached_elevations:
        return cached_elevations
    '''
    WITH src AS
        (SELECT ST_DumpPoints(flights.locations) AS location,
                flights.timestamps AS timestamps,
                flights.locations AS locations
        FROM flights
        WHERE flights.id = 30000)
    SELECT timestamps[(src.location).path[1]] AS timestamp,
           ST_Value(elevations.rast, (src.location).geom) AS elevation
    FROM elevations, src
    WHERE src.locations && elevations.rast AND (src.location).geom && elevations.rast;
    '''

    # Prepare column expressions
    location = Flight.locations.ST_DumpPoints()

    # Prepare cte
    cte = db.session.query(location.label('location'),
                           Flight.locations.label('locations'),
                           Flight.timestamps.label('timestamps')) \
        .filter(Flight.id == flight.id).cte()

    # Prepare column expressions
    timestamp = literal_column('timestamps[(location).path[1]]')
    elevation = Elevation.rast.ST_Value(cte.c.location.geom)

    # Prepare main query
    q = db.session.query(timestamp.label('timestamp'),
                         elevation.label('elevation')) \
        .filter(and_(cte.c.locations.intersects(Elevation.rast),
                     cte.c.location.geom.intersects(Elevation.rast))).all()

    if len(q) == 0:
        return []

    start_time = q[0][0]
    start_midnight = start_time.replace(hour=0,
                                        minute=0,
                                        second=0,
                                        microsecond=0)

    elevations = []
    for time, elevation in q:
        if elevation is None:
            continue

        time_delta = time - start_midnight
        time = time_delta.days * 86400 + time_delta.seconds

        elevations.append((time, elevation))

    cache.set('elevations_' + flight.__repr__(), elevations, timeout=3600 * 24)

    return elevations
Example #3
0
        trace = _encode_flight_path(fp, qnh=flight.qnh)
        infringements = get_airspace_infringements(fp, qnh=flight.qnh)

        db.session.add(igc_file)
        db.session.add(flight)

        # flush data to make sure we don't get duplicate files from ZIP files
        db.session.flush()

        # Store data in cache for image creation
        cache_key = hashlib.sha1(str(flight.id) + '_' +
                                 str(current_user.id)).hexdigest()

        cache.set('upload_airspace_infringements_' + cache_key,
                  infringements,
                  timeout=15 * 60)
        cache.set('upload_airspace_flight_path_' + cache_key,
                  fp,
                  timeout=15 * 60)

        airspace = db.session.query(Airspace) \
                             .filter(Airspace.id.in_(infringements.keys())) \
                             .all()

        results.append(
            UploadResult(name, flight, UploadStatus.SUCCESS, str(prefix),
                         trace, airspace, cache_key))

        create_flight_notifications(flight)
Example #4
0
def index_post():
    current_user = User.get(request.user_id)

    try:
        data = FlightUploadSchema().load(request.form).data
    except ValidationError as e:
        return jsonify(error="validation-failed", fields=e.messages), 422

    pilot_id = data.get("pilot_id")
    if pilot_id:
        pilot = User.get(pilot_id)
        if not pilot:
            return jsonify(error="unknown-pilot"), 422
    else:
        pilot = None

    club_id = (pilot and pilot.club_id) or current_user.club_id

    results = []
    weglide_uploads = []

    _files = request.files.getlist("files")

    prefix = 0
    for name, f in iterate_upload_files(_files):
        prefix += 1
        filename = files.sanitise_filename(name)
        filename = files.add_file(filename, f)

        # check if the file already exists
        with files.open_file(filename) as f:
            md5 = file_md5(f)
            other = Flight.by_md5(md5)
            if other:
                files.delete_file(filename)
                results.append(UploadResult.for_duplicate(name, other, str(prefix)))
                continue

        igc_file = IGCFile()
        igc_file.owner = current_user
        igc_file.filename = filename
        igc_file.md5 = md5
        igc_file.update_igc_headers()

        if igc_file.date_utc is None:
            files.delete_file(filename)
            results.append(UploadResult.for_missing_date(name, str(prefix)))
            continue

        flight = Flight()
        flight.pilot_id = pilot_id
        flight.pilot_name = data.get("pilot_name")
        flight.club_id = club_id
        flight.igc_file = igc_file

        flight.model_id = igc_file.guess_model()

        if igc_file.registration:
            flight.registration = igc_file.registration
        else:
            flight.registration = igc_file.guess_registration()

        flight.competition_id = igc_file.competition_id

        fp = flight_path(flight.igc_file, add_elevation=True, max_points=None)

        analyzed = False
        try:
            analyzed = analyse_flight(flight, fp=fp)
        except:
            current_app.logger.exception("analyse_flight() raised an exception")

        if not analyzed:
            files.delete_file(filename)
            results.append(UploadResult.for_parser_error(name, str(prefix)))
            continue

        if not flight.takeoff_time or not flight.landing_time:
            files.delete_file(filename)
            results.append(UploadResult.for_no_flight(name, str(prefix)))
            continue

        if flight.landing_time > datetime.now():
            files.delete_file(filename)
            results.append(UploadResult.for_future_flight(name, str(prefix)))
            continue

        if not flight.update_flight_path():
            files.delete_file(filename)
            results.append(UploadResult.for_no_flight(name, str(prefix)))
            continue

        flight.privacy_level = Flight.PrivacyLevel.PRIVATE

        trace = _encode_flight_path(fp, qnh=flight.qnh)
        infringements = get_airspace_infringements(fp, qnh=flight.qnh)

        db.session.add(igc_file)
        db.session.add(flight)

        # flush data to make sure we don't get duplicate files from ZIP files
        db.session.flush()

        # Queue WeGlide upload if requested
        weglide_user_id = data.get("weglideUserId")
        weglide_birthday = data.get("weglideBirthday")
        if weglide_user_id and weglide_birthday:
            # Save `upload_to_weglide` task parameters for later. We can't start
            # the task directly here, because the DB transaction has not been
            # committed at this point.
            weglide_uploads.append(
                (igc_file.id, weglide_user_id, weglide_birthday.isoformat())
            )

            # Update `weglide_status` in the database
            igc_file.weglide_status = 1
            db.session.flush()

        # Store data in cache for image creation
        cache_key = hashlib.sha1(
            (to_unicode(flight.id) + u"_" + to_unicode(current_user.id)).encode("utf-8")
        ).hexdigest()

        cache.set(
            "upload_airspace_infringements_" + cache_key, infringements, timeout=15 * 60
        )
        cache.set("upload_airspace_flight_path_" + cache_key, fp, timeout=15 * 60)

        airspace = (
            db.session.query(Airspace)
            .filter(Airspace.id.in_(infringements.keys()))
            .all()
        )

        results.append(
            UploadResult(
                name,
                flight,
                UploadStatus.SUCCESS,
                str(prefix),
                trace,
                airspace,
                cache_key,
            )
        )

        create_flight_notifications(flight)

    db.session.commit()

    # Schedule the deferred WeGlide upload tasks from above
    for weglide_upload in weglide_uploads:
        tasks.upload_to_weglide.delay(*weglide_upload)

    results = UploadResultSchema().dump(results, many=True).data

    club_members = []
    if current_user.club_id:
        member_schema = UserSchema(only=("id", "name"))

        club_members = (
            User.query(club_id=current_user.club_id)
            .order_by(func.lower(User.name))
            .filter(User.id != current_user.id)
        )

        club_members = member_schema.dump(club_members.all(), many=True).data

    aircraft_models = (
        AircraftModel.query()
        .order_by(AircraftModel.kind)
        .order_by(AircraftModel.name)
        .all()
    )

    aircraft_models = AircraftModelSchema().dump(aircraft_models, many=True).data

    return jsonify(
        results=results, club_members=club_members, aircraft_models=aircraft_models
    )
Example #5
0
        flight.privacy_level = Flight.PrivacyLevel.PRIVATE

        trace = _encode_flight_path(fp, qnh=flight.qnh)
        infringements = get_airspace_infringements(fp, qnh=flight.qnh)

        db.session.add(igc_file)
        db.session.add(flight)

        # flush data to make sure we don't get duplicate files from ZIP files
        db.session.flush()

        # Store data in cache for image creation
        cache_key = hashlib.sha1(str(flight.id) + '_' + str(current_user.id)).hexdigest()

        cache.set('upload_airspace_infringements_' + cache_key, infringements, timeout=15 * 60)
        cache.set('upload_airspace_flight_path_' + cache_key, fp, timeout=15 * 60)

        airspace = db.session.query(Airspace) \
                             .filter(Airspace.id.in_(infringements.keys())) \
                             .all()

        results.append(UploadResult(name, flight, UploadStatus.SUCCESS, str(prefix), trace, airspace, cache_key))

        create_flight_notifications(flight)

    db.session.commit()

    results = UploadResultSchema().dump(results, many=True).data

    club_members = []
Example #6
0
def index_post():
    current_user = User.get(request.user_id)

    form = request.form

    if form.get("pilotId") == u"":
        form = form.copy()
        form.pop("pilotId")

    try:
        data = FlightSchema(only=("pilotId", "pilotName")).load(form).data
    except ValidationError as e:
        return jsonify(error="validation-failed", fields=e.messages), 422

    pilot_id = data.get("pilot_id")
    pilot = pilot_id and User.get(pilot_id)
    pilot_id = pilot and pilot.id

    club_id = (pilot and pilot.club_id) or current_user.club_id

    results = []

    _files = request.files.getlist("files")

    prefix = 0
    for name, f in iterate_upload_files(_files):
        prefix += 1
        filename = files.sanitise_filename(name)
        filename = files.add_file(filename, f)

        # check if the file already exists
        with files.open_file(filename) as f:
            md5 = file_md5(f)
            other = Flight.by_md5(md5)
            if other:
                files.delete_file(filename)
                results.append(UploadResult.for_duplicate(name, other, str(prefix)))
                continue

        igc_file = IGCFile()
        igc_file.owner = current_user
        igc_file.filename = filename
        igc_file.md5 = md5
        igc_file.update_igc_headers()

        if igc_file.date_utc is None:
            files.delete_file(filename)
            results.append(UploadResult.for_missing_date(name, str(prefix)))
            continue

        flight = Flight()
        flight.pilot_id = pilot_id
        flight.pilot_name = data.get("pilot_name")
        flight.club_id = club_id
        flight.igc_file = igc_file

        flight.model_id = igc_file.guess_model()

        if igc_file.registration:
            flight.registration = igc_file.registration
        else:
            flight.registration = igc_file.guess_registration()

        flight.competition_id = igc_file.competition_id

        fp = flight_path(flight.igc_file, add_elevation=True, max_points=None)

        analyzed = False
        try:
            analyzed = analyse_flight(flight, fp=fp)
        except:
            current_app.logger.exception("analyse_flight() raised an exception")

        if not analyzed:
            files.delete_file(filename)
            results.append(UploadResult.for_parser_error(name, str(prefix)))
            continue

        if not flight.takeoff_time or not flight.landing_time:
            files.delete_file(filename)
            results.append(UploadResult.for_no_flight(name, str(prefix)))
            continue

        if flight.landing_time > datetime.now():
            files.delete_file(filename)
            results.append(UploadResult.for_future_flight(name, str(prefix)))
            continue

        if not flight.update_flight_path():
            files.delete_file(filename)
            results.append(UploadResult.for_no_flight(name, str(prefix)))
            continue

        flight.privacy_level = Flight.PrivacyLevel.PRIVATE

        trace = _encode_flight_path(fp, qnh=flight.qnh)
        infringements = get_airspace_infringements(fp, qnh=flight.qnh)

        db.session.add(igc_file)
        db.session.add(flight)

        # flush data to make sure we don't get duplicate files from ZIP files
        db.session.flush()

        # Store data in cache for image creation
        cache_key = hashlib.sha1(
            (to_unicode(flight.id) + u"_" + to_unicode(current_user.id)).encode("utf-8")
        ).hexdigest()

        cache.set(
            "upload_airspace_infringements_" + cache_key, infringements, timeout=15 * 60
        )
        cache.set("upload_airspace_flight_path_" + cache_key, fp, timeout=15 * 60)

        airspace = (
            db.session.query(Airspace)
            .filter(Airspace.id.in_(infringements.keys()))
            .all()
        )

        results.append(
            UploadResult(
                name,
                flight,
                UploadStatus.SUCCESS,
                str(prefix),
                trace,
                airspace,
                cache_key,
            )
        )

        create_flight_notifications(flight)

    db.session.commit()

    results = UploadResultSchema().dump(results, many=True).data

    club_members = []
    if current_user.club_id:
        member_schema = UserSchema(only=("id", "name"))

        club_members = (
            User.query(club_id=current_user.club_id)
            .order_by(func.lower(User.name))
            .filter(User.id != current_user.id)
        )

        club_members = member_schema.dump(club_members.all(), many=True).data

    aircraft_models = (
        AircraftModel.query()
        .order_by(AircraftModel.kind)
        .order_by(AircraftModel.name)
        .all()
    )

    aircraft_models = AircraftModelSchema().dump(aircraft_models, many=True).data

    return jsonify(
        results=results, club_members=club_members, aircraft_models=aircraft_models
    )