示例#1
0
    def update_flight_path(self):
        from skylines.lib.xcsoar_ import flight_path
        from skylines.lib.datetime import from_seconds_of_day

        # Run the IGC file through the FlightPath utility
        path = flight_path(self.igc_file, qnh=self.qnh)
        if len(path) < 2:
            return False

        # Save the timestamps of the coordinates
        date_utc = self.igc_file.date_utc
        self.timestamps = [
            from_seconds_of_day(date_utc, c.seconds_of_day) for c in path
        ]

        # Convert the coordinate into a list of tuples
        coordinates = [(c.location["longitude"], c.location["latitude"]) for c in path]

        # Create a shapely LineString object from the coordinates
        linestring = LineString(coordinates)

        # Save the new path as WKB
        self.locations = from_shape(linestring, srid=4326)

        return True
示例#2
0
    def update_flight_path(self):
        from skylines.lib.xcsoar_ import flight_path
        from skylines.lib.datetime import from_seconds_of_day

        # Run the IGC file through the FlightPath utility
        path = flight_path(self.igc_file, qnh=self.qnh)
        if len(path) < 2:
            return False

        # Save the timestamps of the coordinates
        date_utc = self.igc_file.date_utc
        self.timestamps = \
            [from_seconds_of_day(date_utc, c.seconds_of_day) for c in path]

        # Convert the coordinate into a list of tuples
        coordinates = [(c.location['longitude'], c.location['latitude'])
                       for c in path]

        # Create a shapely LineString object from the coordinates
        linestring = LineString(coordinates)

        # Save the new path as WKB
        self.locations = from_shape(linestring, srid=4326)

        return True
示例#3
0
文件: flight.py 项目: imclab/skylines
def _get_flight_path(flight, threshold=0.001, max_points=3000):
    fp = flight_path(flight.igc_file, max_points)
    if len(fp) == 0:
        current_app.logger.error('flight_path("' + flight.igc_file.filename + '") returned with an empty list')
        return None

    num_levels = 4
    zoom_factor = 4
    zoom_levels = [0]
    zoom_levels.extend([round(-math.log(32.0 / 45.0 * (threshold * pow(zoom_factor, num_levels - i - 1)), 2)) for i in range(1, num_levels)])

    max_delta_time = max(4, (fp[-1].seconds_of_day - fp[0].seconds_of_day) / 500)

    encoder = SkyLinesPolyEncoder(num_levels=4, threshold=threshold, zoom_factor=4)

    fixes = map(lambda x: (x.longitude, x.latitude,
                           (x.seconds_of_day / max_delta_time * threshold)), fp)
    fixes = encoder.classify(fixes, remove=False, type="ppd")

    encoded = encoder.encode(fixes['points'], fixes['levels'])

    barogram_t = encoder.encodeList([fp[i].seconds_of_day for i in range(len(fp)) if fixes['levels'][i] != -1])
    barogram_h = encoder.encodeList([fp[i].altitude for i in range(len(fp)) if fixes['levels'][i] != -1])
    enl = encoder.encodeList([fp[i].enl for i in range(len(fp)) if fixes['levels'][i] != -1])

    elevations_t, elevations_h = _get_elevations(flight, encoder)
    contest_traces = _get_contest_traces(flight, encoder)

    return dict(encoded=encoded, zoom_levels=zoom_levels, num_levels=num_levels,
                barogram_t=barogram_t, barogram_h=barogram_h,
                enl=enl, contests=contest_traces,
                elevations_t=elevations_t, elevations_h=elevations_h,
                sfid=flight.id)
示例#4
0
文件: flight.py 项目: kedder/skylines
def _get_flight_path(flight, threshold=0.001, max_points=3000):
    fp = flight_path(flight.igc_file, max_points)
    if len(fp) == 0:
        current_app.logger.error('flight_path("' + flight.igc_file.filename + '") returned with an empty list')
        return None

    num_levels = 4
    zoom_factor = 4
    zoom_levels = [0]
    zoom_levels.extend([round(-math.log(32.0 / 45.0 * (threshold * pow(zoom_factor, num_levels - i - 1)), 2)) for i in range(1, num_levels)])

    max_delta_time = max(4, (fp[-1].seconds_of_day - fp[0].seconds_of_day) / 500)

    encoder = SkyLinesPolyEncoder(num_levels=4, threshold=threshold, zoom_factor=4)

    fixes = map(lambda x: (x.longitude, x.latitude,
                           (x.seconds_of_day / max_delta_time * threshold)), fp)
    fixes = encoder.classify(fixes, remove=False, type="ppd")

    encoded = encoder.encode(fixes['points'], fixes['levels'])

    barogram_t = encoder.encodeList([fp[i].seconds_of_day for i in range(len(fp)) if fixes['levels'][i] != -1])
    barogram_h = encoder.encodeList([fp[i].altitude for i in range(len(fp)) if fixes['levels'][i] != -1])
    enl = encoder.encodeList([fp[i].enl for i in range(len(fp)) if fixes['levels'][i] != -1])

    elevations_t, elevations_h = _get_elevations(flight, encoder)
    contest_traces = _get_contest_traces(flight, encoder)

    return dict(encoded=encoded, zoom_levels=zoom_levels, num_levels=num_levels,
                barogram_t=barogram_t, barogram_h=barogram_h,
                enl=enl, contests=contest_traces,
                elevations_t=elevations_t, elevations_h=elevations_h,
                sfid=flight.id)
示例#5
0
    def update_flight_path(flight):
        from skylines.lib.xcsoar_ import flight_path
        from skylines.lib.datetime import from_seconds_of_day

        # Now populate the FlightPathChunks table with the (full) flight path
        path_detailed = flight_path(flight.igc_file,
                                    max_points=3000,
                                    qnh=flight.qnh)
        if len(path_detailed) < 2:
            return False

        # Number of points in each chunck.
        num_points = 100

        # Interval of the current chunck: [i, j] (-> path_detailed[i:j + 1])
        i = 0
        j = min(num_points - 1, len(path_detailed) - 1)

        # Ensure that the last chunk contains at least two fixes
        if j == len(path_detailed) - 2:
            j = len(path_detailed) - 1

        FlightPathChunks.query().filter(
            FlightPathChunks.flight == flight).delete()
        date_utc = flight.igc_file.date_utc

        while True:
            flight_path = FlightPathChunks(flight=flight)

            # Save the timestamps of the coordinates
            flight_path.timestamps = \
                [from_seconds_of_day(date_utc, c.seconds_of_day) for c in path_detailed[i:j + 1]]

            flight_path.start_time = path_detailed[i].datetime
            flight_path.end_time = path_detailed[j].datetime

            # Convert the coordinate into a list of tuples
            coordinates = [(c.location['longitude'], c.location['latitude'])
                           for c in path_detailed[i:j + 1]]

            # Create a shapely LineString object from the coordinates
            linestring = LineString(coordinates)

            # Save the new path as WKB
            flight_path.locations = from_shape(linestring, srid=4326)

            db.session.add(flight_path)

            if j == len(path_detailed) - 1:
                break
            else:
                i = j + 1
                j = min(j + num_points, len(path_detailed) - 1)

                if j == len(path_detailed) - 2:
                    j = len(path_detailed) - 1

        db.session.commit()

        return True
示例#6
0
    def update_flight_path(flight):
        from skylines.lib.xcsoar_ import flight_path
        from skylines.lib.datetime import from_seconds_of_day

        # Now populate the FlightPathChunks table with the (full) flight path
        path_detailed = flight_path(flight.igc_file, max_points=3000, qnh=flight.qnh)
        if len(path_detailed) < 2:
            return False

        # Number of points in each chunck.
        num_points = 100

        # Interval of the current chunck: [i, j] (-> path_detailed[i:j + 1])
        i = 0
        j = min(num_points - 1, len(path_detailed) - 1)

        # Ensure that the last chunk contains at least two fixes
        if j == len(path_detailed) - 2:
            j = len(path_detailed) - 1

        FlightPathChunks.query().filter(FlightPathChunks.flight == flight).delete()
        date_utc = flight.igc_file.date_utc

        while True:
            flight_path = FlightPathChunks(flight=flight)

            # Save the timestamps of the coordinates
            flight_path.timestamps = \
                [from_seconds_of_day(date_utc, c.seconds_of_day) for c in path_detailed[i:j + 1]]

            flight_path.start_time = path_detailed[i].datetime
            flight_path.end_time = path_detailed[j].datetime

            # Convert the coordinate into a list of tuples
            coordinates = [(c.location['longitude'], c.location['latitude']) for c in path_detailed[i:j + 1]]

            # Create a shapely LineString object from the coordinates
            linestring = LineString(coordinates)

            # Save the new path as WKB
            flight_path.locations = from_shape(linestring, srid=4326)

            db.session.add(flight_path)

            if j == len(path_detailed) - 1:
                break
            else:
                i = j + 1
                j = min(j + num_points, len(path_detailed) - 1)

                if j == len(path_detailed) - 2:
                    j = len(path_detailed) - 1

        db.session.commit()

        return True
示例#7
0
文件: upload.py 项目: tazle/skylines
def _get_flight_path(flight):
    fp = flight_path(flight.igc_file, add_elevation=True)

    barogram_h = xcsoar.encode([fix.altitude for fix in fp], method="signed")
    barogram_t = xcsoar.encode([fix.seconds_of_day for fix in fp], method="signed")
    enl = xcsoar.encode([fix.enl if fix.enl is not None else 0 for fix in fp], method="signed")
    elevations_h = xcsoar.encode([fix.elevation if fix.elevation is not None else -1000 for fix in fp], method="signed")

    return dict(barogram_h=barogram_h, barogram_t=barogram_t,
                enl=enl, elevations_h=elevations_h,
                igc_start_time=fp[0].datetime, igc_end_time=fp[-1].datetime)
示例#8
0
def check_update_form(prefix, status):
    form = UploadUpdateForm(prefix=str(prefix))

    if not form.id or not form.id.data:
        return None, None, None

    flight_id = form.id.data

    # Get flight from database and check if it is writable
    flight = Flight.get(flight_id)

    if not flight:
        abort(404)

    if status == UploadStatus.DUPLICATE:
        return flight, None, None

    else:
        if not flight.is_writable(g.current_user):
            abort(403)

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

        form.populate_obj(flight)

        # replace None in form.pilot_id and form.co_pilot_id with 0
        if not form.pilot_id.data: form.pilot_id.data = 0
        if not form.co_pilot_id.data: form.co_pilot_id.data = 0

        # Force takeoff_time and landing_time to be within the igc file limits
        if form.takeoff_time.data < fp[0].datetime:
            form.takeoff_time.data = fp[0].datetime

        if form.landing_time.data > fp[-1].datetime:
            form.landing_time.data = fp[-1].datetime

        return flight, fp, form
示例#9
0
def check_update_form(prefix, status):
    form = UploadUpdateForm(prefix=str(prefix))

    if not form.id or not form.id.data:
        return None, None, None

    flight_id = form.id.data

    # Get flight from database and check if it is writable
    flight = Flight.get(flight_id)

    if not flight:
        abort(404)

    if status == UploadStatus.DUPLICATE:
        return flight, None, None

    else:
        if not flight.is_writable(g.current_user):
            abort(403)

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

        form.populate_obj(flight)

        # replace None in form.pilot_id and form.co_pilot_id with 0
        if not form.pilot_id.data: form.pilot_id.data = 0
        if not form.co_pilot_id.data: form.co_pilot_id.data = 0

        # Force takeoff_time and landing_time to be within the igc file limits
        if form.takeoff_time.data < fp[0].datetime:
            form.takeoff_time.data = fp[0].datetime

        if form.landing_time.data > fp[-1].datetime:
            form.landing_time.data = fp[-1].datetime

        return flight, fp, form
示例#10
0
        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)))
示例#11
0
def index_post(form):
    user = g.current_user

    pilot_id = form.pilot.data if form.pilot.data != 0 else None
    pilot = pilot_id and User.get(int(pilot_id))
    pilot_id = pilot and pilot.id

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

    flights = []
    success = False

    prefix = 0
    for name, f in IterateUploadFiles(form.file.raw_data):
        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)
                flights.append((name, other, UploadStatus.DUPLICATE, str(prefix), None, None, None, None))
                continue

        igc_file = IGCFile()
        igc_file.owner = 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)
            flights.append((name, None, UploadStatus.MISSING_DATE, str(prefix), None, None, None, None))
            continue

        flight = Flight()
        flight.pilot_id = pilot_id
        flight.pilot_name = form.pilot_name.data if form.pilot_name.data else None
        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:
            analyse_flight(flight, fp=fp)
            analyzed = True
        except:
            current_app.logger.exception('analyse_flight() raised an exception')

        if not analyzed:
            files.delete_file(filename)
            flights.append((name, None, UploadStatus.PARSER_ERROR, str(prefix), None, None, None, None))
            continue

        if not flight.takeoff_time or not flight.landing_time:
            files.delete_file(filename)
            flights.append((name, None, UploadStatus.NO_FLIGHT, str(prefix), None, None, None, None))
            continue

        if flight.landing_time > datetime.now():
            files.delete_file(filename)
            flights.append((name, None, UploadStatus.FLIGHT_IN_FUTURE, str(prefix), None, None, None, None))
            continue

        if not flight.update_flight_path():
            files.delete_file(filename)
            flights.append((name, None, UploadStatus.NO_FLIGHT, str(prefix), None, None, None, None))
            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(str(flight.id) + '_' + str(user.id)).hexdigest()

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

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

        # create form after flushing the session, otherwise we wouldn't have a flight.id
        form = UploadUpdateForm(formdata=None, prefix=str(prefix), obj=flight)
        # remove airspace field from form if no airspace infringements found
        if not infringements:
            del form.airspace_usage

        # replace None in form.pilot_id and form.co_pilot_id with 0
        if not form.pilot_id.data: form.pilot_id.data = 0
        if not form.co_pilot_id.data: form.co_pilot_id.data = 0

        form.pilot_id.validate(form)

        flights.append((name, flight, UploadStatus.SUCCESS, str(prefix), trace,
                        airspace, cache_key, form))

        create_flight_notifications(flight)

        success = True

    db.session.commit()

    if success:
        flash(_('Please click "Publish Flight(s)" at the bottom to confirm our automatic analysis.'))

    return render_template(
        'upload/result.jinja', num_flights=prefix, flights=flights, success=success)
示例#12
0
        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)
示例#13
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
    )
示例#14
0
def index_post(form):
    user = g.current_user

    pilot_id = form.pilot.data if form.pilot.data != 0 else None
    pilot = pilot_id and User.get(int(pilot_id))
    pilot_id = pilot and pilot.id

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

    results = []
    success = False

    prefix = 0
    for name, f in iterate_upload_files(form.file.raw_data):
        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 = 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 = form.pilot_name.data if form.pilot_name.data else None
        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(str(flight.id) + '_' + str(user.id)).hexdigest()

        current_app.cache.set('upload_airspace_infringements_' + cache_key, infringements, timeout=15 * 60)
        current_app.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)

        success = True

    db.session.commit()

    if success:
        flash(_('Please click "Publish Flight(s)" at the bottom to confirm our automatic analysis.'))

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

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

        club_members = User.query(club_id=g.current_user.club_id) \
            .order_by(func.lower(User.name)) \
            .filter(User.id != g.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 render_template(
        'upload/result.jinja', num_flights=prefix, results=results, success=success,
        results_json=results_json, club_members=club_members, aircraft_models=aircraft_models)
示例#15
0
def index_post(form):
    user = g.current_user

    pilot_id = form.pilot.data if form.pilot.data != 0 else None
    pilot = pilot_id and User.get(int(pilot_id))
    pilot_id = pilot and pilot.id

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

    results = []
    success = False

    prefix = 0
    for name, f in iterate_upload_files(form.file.raw_data):
        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 = 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 = form.pilot_name.data if form.pilot_name.data else None
        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(str(flight.id) + '_' +
                                 str(user.id)).hexdigest()

        current_app.cache.set('upload_airspace_infringements_' + cache_key,
                              infringements,
                              timeout=15 * 60)
        current_app.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)

        success = True

    db.session.commit()

    if success:
        flash(
            _('Please click "Publish Flight(s)" at the bottom to confirm our automatic analysis.'
              ))

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

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

        club_members = User.query(club_id=g.current_user.club_id) \
            .order_by(func.lower(User.name)) \
            .filter(User.id != g.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 render_template('upload/result.jinja',
                           num_flights=prefix,
                           results=results,
                           success=success,
                           results_json=results_json,
                           club_members=club_members,
                           aircraft_models=aircraft_models)
示例#16
0
def index_post(form):
    user = g.current_user

    pilot_id = form.pilot.data if form.pilot.data != 0 else None
    pilot = pilot_id and User.get(int(pilot_id))
    pilot_id = pilot and pilot.id

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

    flights = []
    success = False

    prefix = 0
    for name, f in IterateUploadFiles(form.file.raw_data):
        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)
                flights.append((name, other, UploadStatus.DUPLICATE, str(prefix), None, None, None, None))
                continue

        igc_file = IGCFile()
        igc_file.owner = 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)
            flights.append((name, None, UploadStatus.MISSING_DATE, str(prefix), None, None, None, None))
            continue

        flight = Flight()
        flight.pilot_id = pilot_id
        flight.pilot_name = form.pilot_name.data if form.pilot_name.data else None
        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)

        if not analyse_flight(flight, fp=fp):
            files.delete_file(filename)
            flights.append((name, None, UploadStatus.PARSER_ERROR, str(prefix), None, None, None, None))
            continue

        if not flight.takeoff_time or not flight.landing_time:
            files.delete_file(filename)
            flights.append((name, None, UploadStatus.NO_FLIGHT, str(prefix), None, None, None, None))
            continue

        if flight.landing_time > datetime.now():
            files.delete_file(filename)
            flights.append((name, None, UploadStatus.FLIGHT_IN_FUTURE, str(prefix), None, None, None, None))
            continue

        if not flight.update_flight_path():
            files.delete_file(filename)
            flights.append((name, None, UploadStatus.NO_FLIGHT, str(prefix), None, None, None, None))
            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(str(flight.id) + '_' + str(user.id)).hexdigest()

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

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

        # create form after flushing the session, otherwise we wouldn't have a flight.id
        form = UploadUpdateForm(formdata=None, prefix=str(prefix), obj=flight)
        # remove airspace field from form if no airspace infringements found
        if not infringements:
            del form.airspace_usage

        # replace None in form.pilot_id and form.co_pilot_id with 0
        if not form.pilot_id.data: form.pilot_id.data = 0
        if not form.co_pilot_id.data: form.co_pilot_id.data = 0

        form.pilot_id.validate(form)

        flights.append((name, flight, UploadStatus.SUCCESS, str(prefix), trace,
                        airspace, cache_key, form))

        create_flight_notifications(flight)

        success = True

    db.session.commit()

    if success:
        flash(_('Please click "Publish Flight(s)" at the bottom to confirm our automatic analysis.'))

    return render_template(
        'upload/result.jinja', num_flights=prefix, flights=flights, success=success)
示例#17
0
 def get_constant_elevation(flight):
     path = flight_path(flight.igc_file)
     return ((fix.seconds_of_day, elevation) for fix in path)
示例#18
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
    )
 def get_constant_elevation(flight):
     path = flight_path(flight.igc_file)
     return ((fix.seconds_of_day, elevation) for fix in path)