def system_career_graph(id): system = System.query.filter_by(id=id).one() stations = system.stations limit = today_datetime() datasets = [] CBS = CareerBatchSubmission # colors from https://htmlcolorcodes.com/color-chart/ colors = '#cd6155 #9b59b6 #2980b9 #1abc9c #16a085 #f1c40f #f39c12 #7f8c8d #f1948a #85c1e9'.split( ' ') for idx, station in enumerate(stations): data = [] q = CBS.query.filter(CBS.station_id == station.id, CBS.when <= limit).order_by(CBS.when) for batch in q: if batch.factor: data.append({ 'x': batch.when.strftime("%Y-%m-%dT%H:%M:%SZ"), 'y': batch.factor }) if data: datasets.append({ 'label': station.name, 'data': data, 'backgroundColor': colors[idx], }) ctx = { 'system': system, 'datasets': json.dumps(datasets), 'systems': System.query.all() } return render_template('system_career_factor.html', **ctx)
def render_fuel_add_response(current_station, token): start_dt = now() reference_date = today_datetime() rows = [] seen = set() for stat in FPS.query.filter(FPS.last_reading >= reference_date).order_by( FPS.last_price, FPS.station_name): station_name = stat.station_short_name or stat.station_name seen.add(station_name) diff = start_dt - stat.last_reading rows.append({ 'station_name': station_name, 'is_current': stat.station_id == current_station.id, 'price_per_g': stat.last_price, 'age': gct_duration(start_dt - stat.last_reading), }) # add estimations estimations = [ e for e in FuelPriceEstimation.all_today() if e.station.short not in seen ] for e in estimations: rows.append({ 'station_name': e.station.short, 'is_current': False, 'price_per_g': e.price_per_g, 'age': '(est.)', }) rows.sort(key=lambda e: e['price_per_g']) return str(render_template('fuel_short_table.html', rows=rows, token=token))
def system_fuel_price(id): system = System.query.filter_by(id=id).one() stations = system.stations limit = today_datetime() datasets = [] colors = '#cd6155 #9b59b6 #2980b9 #1abc9c #16a085 #f1c40f #f39c12 #7f8c8d #f1948a #85c1e9'.split( ' ') FPR = FuelPriceReading for idx, station in enumerate(stations): data = [] q = FPR.query.filter(FPR.station_id == station.id, FPR.when < limit).order_by(FPR.when.asc()) for reading in q.all(): data.append({ 'x': reading.when.strftime("%Y-%m-%dT%H:%M:%SZ"), 'y': reading.price_per_g }) if data: datasets.append({ 'label': station.name, 'data': data, 'borderColor': colors[idx], }) ctx = { 'system': system, 'datasets': json.dumps(datasets), 'systems': System.query.all() } return render_template('system_fuel_price.html', **ctx)
def career_station_needs_update(system, station): try: st = get_station(system, station, create=False) except AssertionError: return jsonify({'needs_update': True}) existing = CareerBatchSubmission.query.filter(CareerBatchSubmission.when > today_datetime()).filter_by(station_id=st.id) \ .order_by(CareerBatchSubmission.when.desc()).first() result = existing is None return jsonify({'needs_update': result})
def fuel_lowest(token): token = Token.query.filter_by(token=token).first() assert token, 'Need valid token' compare = bool(request.args.get('cmp', False)) n = now() limit = today_datetime() refuel = FPS.query.filter(FPS.last_reading > limit).order_by( FPS.last_price.asc()) measured = {r.station_short_name: r.last_price for r in refuel} measured_ts = {r.station_short_name: r.last_reading for r in refuel} estimations = FuelPriceEstimation.today_as_dict() all_short_names = set(estimations.keys()) | set(measured.keys()) rows = [{ 'station_short_name': short, 'last_price': measured.get(short), 'measured_timestamp': measured_ts.get(short), 'estimated_price': estimations.get(short), } for short in all_short_names] if compare: for row in rows: if row['last_price'] and row['estimated_price']: error = 1000 * abs(row['last_price'] - row['estimated_price'] ) / row['estimated_price'] row['error'] = error if error < 5: classification = 'good' elif error < 20: classification = 'ok' else: classification = 'bad' row['classification'] = classification rows.sort(key=lambda r: r['last_price'] or r['estimated_price']) return render_template('fuel_refuel.html', rows=rows, compare=compare)
def fuel_stats_json(token): token = Token.query.filter_by(token=token).first() assert token, 'Need valid token' n = now() estimations = FuelPriceEstimation.today_as_dict() ref_dt = today_datetime() def make_output_dict(r): has_current_reading = r.last_reading >= ref_dt common = { 'station_short_name': r.station_short_name, 'estimation': estimations.get(r.station_short_name), 'station_name': r.station_name, 'system_name': r.system_name, 'min_price': r.min_price, 'max_price': r.max_price, } if has_current_reading: return dict( **common, last_price=r.last_price, last_reading=r.last_reading.isoformat(), ) elif common['estimation'] is not None: return common else: return None rows = [] for r in FPS.query.order_by(FPS.last_price.asc()): d = make_output_dict(r) if d is not None: rows.append(d) rows.sort(key=lambda r: r.get('last_price') or r.get('estimation')) return jsonify({'stations': rows})
def career_task_add(): payload = request.get_json(force=True) mandatory = set(('token', 'station', 'system', 'career', 'rank', 'tasks')) missing_attrs = [a for a in mandatory if not payload.get(a)] if missing_attrs: message = 'Missing attributes: ' + ', '.join(missing_attrs) return jsonify({ 'recorded': False, 'missing': missing_attrs, message: message }) station_name = payload['station'] try: token = Token.verify(payload['token']) token.record_script_version(payload.get('script_version')) except InvalidTokenException: return jsonify({'recorded': False, 'message': 'Invalid token'}) if token is None: return jsonify({'recorded': False, 'message': 'Invalid token'}) if 'Confined to the' in station_name or 'Doing activity' in station_name: return jsonify({ 'recorded': False, 'message': '{} does not look like a valid station name'.format(station_name) }) station = get_station(payload['system'], station_name) batch = CareerBatchSubmission( token=token, character=token.character, station=station, career=payload['career'], rank=payload['rank'], ) db.session.add(batch) response = {'character': token.character.name} factors = [] for task, bonus in payload['tasks'].items(): bonus = float(bonus) career_task = CareerTask.query.filter_by(name=task).first() if career_task is None: career_task = CareerTask( name=task, career=payload['career'], bonus_baseline=bonus, ) db.session.add(career_task) elif career_task.bonus_baseline is None or career_task.bonus_baseline > bonus: career_task.bonus_baseline = bonus tr = CareerTaskReading( batch_submission=batch, career_task=career_task, bonus=bonus, ) db.session.add(tr) f = tr.factor factors.append(f) if f > 2.1: print( 'SUSPICIOUS READING of factor {}, station {}, task {}, token {}' .format( f, station_name, task, token.id, )) factor = max(factors) batch.factor = factor if factor: print('Recorded factor {} for station {}, {}'.format( factor, station.name, datetime.now())) response['recorded'] = True response['factor'] = factor # find factors for other stations in the system date_limit = today_datetime() stations = Station.query.filter_by(system_id=station.system_id) system_factors = {} cbs = CareerBatchSubmission for st in stations.all(): if st.name == station_name: continue qry = cbs.query.filter(cbs.when > date_limit).filter_by( station_id=st.id).order_by(cbs.when.desc()) bs = qry.first() if bs: factor = max(o.factor for o in bs.readings) system_factors[st.name] = factor if system_factors: response['system_factors'] = system_factors db.session.commit() return jsonify(response)