7 Commits
11 changed files with 95 additions and 53 deletions
+1
View File
@@ -1 +1,2 @@
__pycache__
venv/
+19 -3
View File
@@ -1,7 +1,7 @@
<br>
<p align="center">
<img align="center" src="media/cover.png">
<h3 align="center">VATSIM Fox</h3>
<h3 align="center">VATSIM Fox — v1.2</h3>
<p align="center">Website to find out your detailed VATSIM stastic</p>
</p>
<br>
@@ -11,10 +11,10 @@
Project based on [Virtual Air Traffic Simulation Network (VATSIM) API](https://vatsim.dev/).
Written in Python 3.7.10 + JS (JQuery framework) + Boostrap
Written in Python 3.8.18 + JS (JQuery framework) + Boostrap
## Startup
For run application on your own machine, you must install docker. Then just one command in the "src" folder with the project source code:
To run application on your own machine, you must install docker. Then just one command in the "src" folder with the project source code:
```bash
docker compose up
@@ -25,6 +25,22 @@ Any help with this project would be greatly appreciated. Fixes or some features
VATSIM Fox is free software, open to suggestions and contributions. All the files are under the MIT License.
### How to set virtual environment
```bash
# you must be in "src" folder before init
cd src
python -m venv venv
.\venv\Scripts\activate
# downloading requirements && upgrading pip
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
# starting application
python -m flask run --host 0.0.0.0 --debug
```
## Feature
There is small TODO list I would like to make in this project:
-1
View File
@@ -1,3 +1,2 @@
[flake8]
exclude = .git, pycache, .env, .venv
max-line-length = 120
+1 -1
View File
@@ -1,4 +1,4 @@
FROM python:3.7.10
FROM python:3.8.18
WORKDIR /build/
+8 -7
View File
@@ -1,5 +1,5 @@
from flask import Flask, render_template, abort, request, jsonify
import requests
from flask import Flask, render_template, abort, request, jsonify
app = Flask(__name__)
@@ -15,15 +15,16 @@ def index_page():
def errorhandler_page(_):
return render_template("4O4.html"), 404
# Custom wrapper to fetch VATSIM data
@app.route("/api/request")
def request_handler():
request_string = request.args.get("request_string")
if request_string:
if request_string := request.args.get("request_string"):
try:
return requests.get(f"{VATSIM_API_URL}{request_string}").json()
except requests.exceptions.JSONDecodeError:
return jsonify({"result": "error", "message": "Something went wrong. Report that error please"})
return jsonify({"result": "not found"})
return jsonify({"result": "not found", "message": "Not found"})
@app.route("/<int:cid>/")
@@ -33,7 +34,7 @@ def viewer_page(cid):
if "detail" in user and user["detail"] == "Not Found":
return abort(404)
return render_template("viewer.html", data=(user, ))
return render_template("viewer.html", user=user)
if __name__ == "__main__":
+4
View File
@@ -6,3 +6,7 @@
.fox_active, .fox_atc_active {
background-color: #dee2e6 !important;
}
#notification_wrapper {
display: none;
}
+13 -5
View File
@@ -2,8 +2,10 @@
let userSession = {};
fetch(ATC_API_URL, {}).then(response => response.json()).then(result => {
if (result && result["result"] == "not found")
return
if (result && (result["result"] == "not found" || result["result"] == "error")) {
showAlert("Error while getting ATC information", result["message"]);
return;
}
for (let session of result["items"]) {
// Separate each session by it's connection ID
@@ -72,13 +74,13 @@ $.getJSON("/static/data/airports.json", function(json) {
// Map creation
const MAP_ELEMENT = L.map("fox_map");
const MAP_DEFAULT_TARGET = L.latLng("47.50737", "19.04611");
const MAP_DEFAULT_ZOOM_VIEW = 14;
const MAP_DEFAULT_ZOOM_VIEW = 2;
const MAP_DEFAULT_TARGET = L.latLng("0", "0");
let line = null;
MAP_ELEMENT.setView(MAP_DEFAULT_TARGET, MAP_DEFAULT_ZOOM_VIEW);
L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", {
L.tileLayer("https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png", {
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
subdomains: "abcd",
maxZoom: 20,
@@ -153,3 +155,9 @@ function showSession(session) {
$(".atc_transfers").text(session["handoffsinitiated"]);
$(".atc_received").text(session["handoffsreceived"]);
}
function showAlert(title, message) {
$("#notification_wrapper").css("display", "block");
$("#notification_title").text(title);
$("#notification_message").text(message);
}
+13 -7
View File
@@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="description" content="VATSIM Fox — see your detailed profile statistic">
<meta name="description" content="VATSIM Fox — check your detailed profile statistic">
<meta name="keywords" content="VATSIM FOX, fox, vatsim, vatsim statistic, statistic, vatsim fox, flight simulator">
<meta name="author" content="uw935">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -18,7 +18,19 @@
{% block header_css %}{% endblock %}
</head>
<style>
.btn-outline-primary:hover, .btn-outline-primary:active {
color: white !important;
background-color: var(--main-rgb) !important;
border-color: var(--main-rgb) !important;
}
.btn-outline-primary {
border-color: var(--main-rgb);
color: var(--main-rgb);
}
:root {
--main-rgb: #FA8232;
--bs-primary-rgb: 250, 130, 50
}
</style>
@@ -27,16 +39,10 @@
<div class="container py-4">
<header class="pb-3 mb-4 border-bottom">
<a href="/" class="d-flex align-items-center text-dark text-decoration-none">
<!-- <svg xmlns="http://www.w3.org/2000/svg" width="40" height="32" class="me-2" viewBox="0 0 118 94" role="img"><title>Bootstrap</title><path fill-rule="evenodd" clip-rule="evenodd" d="M24.509 0c-6.733 0-11.715 5.893-11.492 12.284.214 6.14-.064 14.092-2.066 20.577C8.943 39.365 5.547 43.485 0 44.014v5.972c5.547.529 8.943 4.649 10.951 11.153 2.002 6.485 2.28 14.437 2.066 20.577C12.794 88.106 17.776 94 24.51 94H93.5c6.733 0 11.714-5.893 11.491-12.284-.214-6.14.064-14.092 2.066-20.577 2.009-6.504 5.396-10.624 10.943-11.153v-5.972c-5.547-.529-8.934-4.649-10.943-11.153-2.002-6.484-2.28-14.437-2.066-20.577C105.214 5.894 100.233 0 93.5 0H24.508zM80 57.863C80 66.663 73.436 72 62.543 72H44a2 2 0 01-2-2V24a2 2 0 012-2h18.437c9.083 0 15.044 4.92 15.044 12.474 0 5.302-4.01 10.049-9.119 10.88v.277C75.317 46.394 80 51.21 80 57.863zM60.521 28.34H49.948v14.934h8.905c6.884 0 10.68-2.772 10.68-7.727 0-4.643-3.264-7.207-9.012-7.207zM49.948 49.2v16.458H60.91c7.167 0 10.964-2.876 10.964-8.281 0-5.406-3.903-8.178-11.425-8.178H49.948z" fill="currentColor"></path></svg> -->
<span class="fs-4">🦊 VATSIM <span class="text-primary">Fox</span></span>
</a>
</header>
<!-- <div class="mb-4 alert alert-primary" role="alert">
Notification
</div>
-->
{% block content %}{% endblock %}
<footer class="pt-3 mt-4 text-muted border-top">
+3 -3
View File
@@ -7,7 +7,7 @@
<p class="col-md-8 fs-4">See your detailed profile statistic</p>
<div class="d-flex" role="search">
<input class="fox_input form-control me-2" type="number" placeholder="100000" aria-label="CID">
<button class="fox_submit btn btn-outline-success" type="submit">Search</button>
<button class="fox_submit btn btn-outline-primary" type="submit">Search</button>
</div>
<p class="fox_message text-primary col-md-8 fs-4"></p>
</div>
@@ -34,9 +34,9 @@
{% block javascript_code %}
<script type="text/javascript">
$(".fox_submit").click(function() {
const INPUT_CID = 0 + $(".fox_input").val();
const INPUT_CID = $(".fox_input").val();
if ((0 + INPUT_CID) < 100000) {
if (INPUT_CID < 100000) {
$(".fox_message").text("CID should be equal or more than 100000");
return;
}
+12 -5
View File
@@ -1,12 +1,19 @@
{% extends "/include/template.html" %}
{% block title %}User {{user_cid}} statistic — VATSIM Fox{% endblock %}
{% block title %}User {{user["id"]}} statistic — VATSIM Fox{% endblock %}
{% block header_css %}
<link rel="stylesheet" href="{{ url_for('static', filename='viewer.css') }}">
<link href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" rel="stylesheet"/>
{% endblock %}
{% block content %}
<div class="mb-5">
<h2 class="text-center text-primary mb-4">{{data[0]["id"]}}</h2>
<div id="notification_wrapper">
<div class="mb-4 alert alert-warning" role="alert">
<h4 id="notification_title"></h4>
<span id="notification_message"></span>
</div>
</div>
<h2 class="text-center text-primary mb-4">{{user["id"]}}</h2>
<p class="fs-4 text-secondary">Date of registration: <span class="date_registration"></span></p>
</div>
@@ -91,7 +98,7 @@
<div class="col-md" style="height: 321px;">
<div class="h-auto p-5 bg-light border rounded-3">
<h2 class="atc_callsign">UUEE_DEL</h2>
<h2 class="atc_callsign">Callsign</h2>
<span>
<b>Start time:</b>
<span class="atc_start_time"></span>
@@ -133,11 +140,11 @@
{% block javascript_code %}
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"></script>
<script type="text/javascript">
const USER_CID = '{{data[0]["id"]}}';
const USER_CID = '{{user["id"]}}';
const FLIGHTPLANS_API_URL = "/api/request?request_string=members/" + USER_CID + "/flightplans";
const ATC_API_URL = "/api/request?request_string=members/" + USER_CID + "/atc";
$(".date_registration").text("{{data[0]['reg_date']}}".replace("T", " "));
$(".date_registration").text("{{user['reg_date']}}".replace("T", " "));
</script>
<script type="text/javascript" src="{{ url_for('static', filename='viewer.js') }}"></script>
{% endblock %}