Compare commits

..

No commits in common. "e783f8c6145b59a539688d973b43f58ed415c58d" and "e8d48670d16d2c36ef0184567e11da637abbf0ed" have entirely different histories.

28 changed files with 178 additions and 1296 deletions

View File

@ -23,17 +23,18 @@ namespace EFB.Controllers
public IActionResult Index()
{
//Check to see what point on the application the user is at and where they should be sent
UserModel user = HttpContext.Session.GetObject<UserModel>("User");
if (user == null)
UserModel User = HttpContext.Session.GetObject<UserModel>("User");
if (User != null)
{
if (User.Route == null)
{
return RedirectToAction("Index", "Route");
}else{
return RedirectToAction("Index", "App");
}
}else{
return RedirectToAction("Index", "Home");
}
if (user.Route == null)
{
return RedirectToAction("Index", "Route");
}
return View(user);
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]

View File

@ -1,76 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using EFB.Models;
using EFB.Models.JSON;
using EFB.Controllers.Form;
using EFB.Sessions;
namespace EFB.Controllers
{
//[Route("[controller]")]
public class ChartsController : Controller
{
private readonly ILogger<ChartsController> _logger;
public ChartsController(ILogger<ChartsController> logger)
{
_logger = logger;
}
public async Task<IActionResult> Index(string ICAO)
{
UserModel user = HttpContext.Session.GetObject<UserModel>("User");
if (user == null)
{
TempData["Error"] = "Must be logged in to view charts";
return RedirectToAction("Index", "Home");
}
if(ICAO == null)
return View();
if (FormAuthenticator.ValidateICAOCode(ICAO))
{
var charts = await ChartModel.FetchAsync(ICAO);
if (charts != null)
{
ChartModel chartModel = new ChartModel(ICAO, charts);
//Save the current chart into user model for later access
user.CurrentCharts = chartModel;
HttpContext.Session.SetObject("User", user);
return RedirectToAction("ViewCharts");
}
}else
{
TempData["Error"] = "Invalid ICAO";
}
return View();
}
public IActionResult ViewCharts(string chart){
UserModel user = HttpContext.Session.GetObject<UserModel>("User");
if (user != null)
{
ViewChartModel charts = new ViewChartModel(user.CurrentCharts, chart);
if (charts != null)
{
return View("ViewCharts", charts);
}
return RedirectToAction("Index");
}
return RedirectToAction("Index", "Home");
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View("Error!");
}
}
}

View File

@ -1,87 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using EFB.Sessions;
using Microsoft.Extensions.Logging;
using EFB.Models;
using EFB.MongoData;
using EFB.Models.Route;
namespace EFB.Controllers
{
//[Route("[controller]")]
public class FlightsimController : Controller
{
private readonly ILogger<FlightsimController> _logger;
public FlightsimController(ILogger<FlightsimController> logger)
{
_logger = logger;
}
public async Task<IActionResult> Index()
{
//Retrieve and Check current user status
UserModel user = HttpContext.Session.GetObject<UserModel>("User");
if(user == null){
TempData["Error"] = "You must be logged in before you are able to view the FlightSim Page";
return RedirectToAction("Index", "Home");
}
//Retrieve the user's latest sim position and construct it into FlightsimModel
if (user.Route == null){
TempData["Error"] = "You must have a route planned before you are able to view the Flightsim page";
return RedirectToAction("Index", "Route");
}
SimPositionModel latestPositionModel = await Mongo.GetLatestData(user.EMail);
RouteModel route = await RouteModel.StringToRoute(user.Departure, user.Arrival, user.Cruise, user.Route);
IWaypoint closest = DetermineClosest(route, latestPositionModel.LatestPosition);
return View(new FlightsimModel(latestPositionModel, closest));
}
private IWaypoint DetermineClosest(RouteModel route, SimPosition currentPosition){
IWaypoint closest = null;
float closestDistance = float.MaxValue;
//Assuming that we are on the earth for simplicity
IWaypoint waypoint = route.Departure;
while (waypoint.Next != null)
{
int earthRadius = 6371;
float distanceLat = DegreesToRadians(waypoint.Latitude - currentPosition.Latitude);
float distanceLon = DegreesToRadians(waypoint.Longitude - currentPosition.Longitude);
float latitude1 = DegreesToRadians(currentPosition.Latitude);
float latitude2 = DegreesToRadians(waypoint.Latitude);
var a = Math.Sin(distanceLat/2) * Math.Sin(distanceLat/2) + Math.Sin(distanceLon/2) * Math.Sin(distanceLon/2) * Math.Cos(latitude1) * Math.Cos(latitude2);
var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1-a));
float distance = (float)(earthRadius * c);
if (distance < closestDistance)
{
closest = waypoint;
closestDistance = distance;
}
waypoint = waypoint.Next;
}
return closest;
}
private float DegreesToRadians(float degrees){
return (float)(degrees * Math.PI / 180);
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View("Error!");
}
}
}

View File

@ -1,56 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using EFB.Models;
using EFB.Sessions;
namespace EFB.Controllers
{
//[Route("[controller]")]
public class NavdataController : Controller
{
private readonly ILogger<NavdataController> _logger;
public NavdataController(ILogger<NavdataController> logger)
{
_logger = logger;
}
public async Task<IActionResult> Index(string identifier)
{
if (identifier == null)
{//In the event we are just going to the base page1
return View();
}
NavdataModel[] data = null;
if (HttpContext.Session.GetObject<NavdataModel[]>("Navdata") == null)
{//If the navdata needs re-caching
data = await NavdataModel.Populate();
HttpContext.Session.SetObject("Navdata", NavdataModel.MergeSort(ref data, 0, data.Length-1));
}
//get the data out of tempdata and cast it into an array
data = HttpContext.Session.GetObject<NavdataModel[]>("Navdata");
NavdataModel navaid = NavdataModel.BinarySearch(ref data, 0, data.Length-1, identifier);
if (navaid == null)
{
TempData["Error"] = $"Sorry, no Navaid found with the name {identifier}";
}
return View(navaid);
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View("Error!");
}
}
}

View File

@ -46,150 +46,134 @@ namespace EFB.Controllers
public async Task<IActionResult> New(string departure, string arrival, string cruise)
{
UserModel user = HttpContext.Session.GetObject<UserModel>("User");
if (user == null || user.UserToken.IsExpired())
if (!(user == null || user.UserToken.IsExpired()))
{//If the user is still authenticated
return RedirectToAction("Index", "Home");
}
if (FormAuthenticator.ValidateICAOCode(departure) && FormAuthenticator.ValidateICAOCode(arrival))
{//If the user has entered valid ICAOs
if (!FormAuthenticator.ValidateICAOCode(departure) || !FormAuthenticator.ValidateICAOCode(arrival))
{//If the user has entered valid ICAOs
TempData["Error"] = "Invalid Departure or Arrival ICAO";
return RedirectToAction("Index", "Route");
}
uint cruiseAlt;
uint cruiseAlt;
if (uint.TryParse(cruise, out cruiseAlt) && FormAuthenticator.ValidateCruiseAlt(cruiseAlt))
{//If the cruise altitude if within limits.
if (uint.TryParse(cruise, out cruiseAlt) && FormAuthenticator.ValidateCruiseAlt(cruiseAlt))
{//If the cruise altitude if within limits.
//Submit route request...
APIInterface API = new APIInterface();
//Submit route request...
APIInterface API = new APIInterface();
//Prepare data to be send off with request (route)
Dictionary<string, string> headerData = new Dictionary<string, string>();
headerData.Add("Authorization", $"Bearer {user.UserToken.TokenValue}");
//Prepare data to be send off with request (route)
Dictionary<string, string> headerData = new Dictionary<string, string>();
headerData.Add("Authorization", $"Bearer {user.UserToken.TokenValue}");
RouteRequest routeRequest = new RouteRequest()
{
departure = departure,
destination = arrival,
preferredminlevel = cruiseAlt / 1000,
preferredmaxlevel = cruiseAlt / 1000,
};
StringContent content = new StringContent(JsonConvert.SerializeObject(routeRequest), Encoding.UTF8, "application/json");
RouteRequest routeRequest = new RouteRequest()
{
departure = departure,
destination = arrival,
preferredminlevel = cruiseAlt / 1000,
preferredmaxlevel = cruiseAlt / 1000,
};
StringContent content = new StringContent(JsonConvert.SerializeObject(routeRequest), Encoding.UTF8, "application/json");
//Make initial Route Request
var requestRoute = API.Post<string>("https://api.autorouter.aero/v1.0/router", headerData, content);
//Make initial Route Request
var requestRoute = API.Post<string>("https://api.autorouter.aero/v1.0/router", headerData, content);
ResponseModel<string> responseRoute = await requestRoute;
ResponseModel<string> responseRoute = await requestRoute;
if (responseRoute.Error == null)
{//Update User session and add route ID
TokenModel routeToken = new TokenModel()
{
TokenValue = responseRoute.Result.ToString()
};
if (responseRoute.Error == null)
{//Update User session and add route ID
TokenModel routeToken = new TokenModel()
{
TokenValue = responseRoute.Result.ToString()
};
user.RouteToken = routeToken;
HttpContext.Session.SetObject("User", user);
user.RouteToken = routeToken;
HttpContext.Session.SetObject("User", user);
return await Poll(departure, arrival, cruiseAlt);
return await Poll(departure, arrival, cruiseAlt);
}
TempData["Error"] = responseRoute.Error;
return RedirectToAction("Index", "Route");
}
TempData["Error"] = "Invalid Cruise Altitude";
TempData["Departure"] = departure;
TempData["Arrival"] = arrival;
return RedirectToAction("Index", "Route");
}
TempData["Error"] = responseRoute.Error;
TempData["Error"] = "Invalid Departure or Arrival ICAO";
return RedirectToAction("Index", "Route");
}
TempData["Error"] = "Invalid Cruise Altitude";
TempData["Departure"] = departure;
TempData["Arrival"] = arrival;
return RedirectToAction("Index", "Route");
return RedirectToAction("Index", "Home");
}
public async Task<IActionResult> Poll(string departure, string arrival, uint cruise)
{
if (HttpContext.Session.GetString("User") == null)
{//If the user is not currently logged in
TempData["Error"] = "Please login before trying to plan a route";
return RedirectToAction("Index", "Route");
}
if (HttpContext.Session.GetString("User") != null)
{//If the user is currently logged in
UserModel user = HttpContext.Session.GetObject<UserModel>("User");
UserModel user = HttpContext.Session.GetObject<UserModel>("User");
if (user.RouteToken != null)
{//If the user has a route object (e.g, they have been to the route page)
if (user.RouteToken == null)
{//If the user has a route object (e.g, they have been to the route page)
return RedirectToAction("Index", "Route");
}
//Make calls to the server to fetch route
bool collected = false;
int pollCount = 0;
string routeString = "";
//Make calls to the server to fetch route
bool collected = false;
int pollCount = 0;
string routeString = "";
APIInterface API = new APIInterface();
Dictionary<string, string> headerData = new Dictionary<string, string>();
APIInterface API = new APIInterface();
/*-----Chart Fetching Operations--------*/
Dictionary<string, string> headerData = new Dictionary<string, string>();
headerData.Add("Authorization", $"Bearer {user.UserToken.TokenValue}");
var requestDepartureCharts = ChartModel.FetchAsync(departure);
var requestArrivalCharts = ChartModel.FetchAsync(arrival);
/*----------------------------------*/
//Run route Polling
headerData.Add("Authorization", $"Bearer {user.UserToken.TokenValue}");
while (collected == false && pollCount < 15)
{
//Make Polling Request
var pollingRequest = API.Put<List<PollResponse>>($"https://api.autorouter.aero/v1.0/router/{user.RouteToken.TokenValue}/longpoll", headerData, null);
ResponseModel<List<PollResponse>> responsePoll = await pollingRequest;
foreach (var item in responsePoll.Result)
{
if (item.Command == "notvalid" || item.Command == "solution")
while (collected == false && pollCount < 3)
{
collected = true;
routeString = item.FlightPlan;
break;
//Make Polling Request
var pollingRequest = API.Put<List<PollResponse>>($"https://api.autorouter.aero/v1.0/router/{user.RouteToken.TokenValue}/longpoll", headerData, null);
ResponseModel<List<PollResponse>> responsePoll = await pollingRequest;
int routePos = responsePoll.Result.Count - 1;
if (responsePoll.Result[routePos].Command == "solution")
{
collected = true;
routeString = responsePoll.Result[routePos].FlightPlan;
break;
}
Thread.Sleep(3000);
pollCount++;
}
if (collected)
{
//fill in route
string finalRoute = RouteModel.ParseRoute(routeString);
RouteModel route = RouteModel.StringToRoute(departure, arrival, cruise, finalRoute);
user.Route = route;
HttpContext.Session.SetObject("User", user);
return RedirectToAction("Index", "Route");
}
TempData["Error"] = $"Unable to get route after {pollCount} Attempts!";
return RedirectToAction("Index", "Route");
}
else
{
return RedirectToAction("Index", "Route");
}
Thread.Sleep(3000);
pollCount++;
}
if (collected)
else
{
//Get Response from Charts
ChartList departureCharts = await requestDepartureCharts;
if (departureCharts != null)
{
user.DepartureCharts = new ChartModel(departure, departureCharts);
}
ChartList arrivalCharts = await requestArrivalCharts;
if (arrivalCharts != null)
{
user.ArrivalCharts = new ChartModel(arrival, arrivalCharts);
}
//fill in route
string finalRoute = RouteModel.ParseRoute(routeString);
user.Route = finalRoute;
user.Departure = departure;
user.Arrival = arrival;
user.Cruise = cruise;
HttpContext.Session.SetObject("User", user);
return RedirectToAction("Index", "App");
return RedirectToAction("Index", "Route");
}
TempData["Error"] = $"Unable to get route after {pollCount} Attempts!";
return RedirectToAction("Index", "Route");
}

View File

@ -9,7 +9,6 @@ using EFB.Models.JSON;
using Microsoft.Extensions.Logging;
using EFB.Models;
using EFB.Sessions;
using EFB.Controllers.API;
namespace EFB.Controllers
{
@ -31,63 +30,63 @@ namespace EFB.Controllers
public async Task<IActionResult> Login(string email, string password){
if (!Form.FormAuthenticator.ValidateEMail(email))
if (Form.FormAuthenticator.ValidateEMail(email))
{
//API Helper
API.APIInterface API = new API.APIInterface();
//Dictionary of Formdata to be encoded
Dictionary<string, string> formData = new Dictionary<string, string>();
formData.Add("grant_type", "client_credentials");
formData.Add("client_id", email);
formData.Add("client_secret", password);
HttpContent content = new FormUrlEncodedContent(formData);
var request = API.Post<Models.JSON.LoginResponse>("https://api.autorouter.aero/v1.0/oauth2/token", null, content);
//Wait for the response to come through
ResponseModel<LoginResponse> response = await request;
if (response.Error != null)
{
TempData["Error"] = response.Error;
TempData["email"] = email;
return RedirectToAction("Index", "Home");
}else{
//Type cast required but we know response will be of known type
LoginResponse login = response.Result;
//Generate User Session
if (login.error == null)
{
UserModel user = new UserModel{
EMail = email,
UserToken = new TokenModel{
TokenValue = login.access_token,
Expiration = DateTime.UtcNow.AddSeconds(login.expires_in)
}
};
//Using Session Extensions (Store the user session)
HttpContext.Session.SetObject("User", user);
return RedirectToAction("Index", "App");
}else{
TempData["Error"] = login.error_description;
TempData["email"] = email;
return RedirectToAction("Index", "Home");
}
}
}else{
TempData["Error"] = "Please enter a valid E-Mail";
return RedirectToAction("Index", "Home");
}
//API Helper
APIInterface API = new APIInterface();
//Dictionary of Formdata to be encoded
Dictionary<string, string> formData = new Dictionary<string, string>();
formData.Add("grant_type", "client_credentials");
formData.Add("client_id", email);
formData.Add("client_secret", password);
HttpContent content = new FormUrlEncodedContent(formData);
var request = API.Post<Models.JSON.LoginResponse>("https://api.autorouter.aero/v1.0/oauth2/token", null, content);
//Wait for the response to come through
ResponseModel<LoginResponse> response = await request;
if (response.Error != null)
{
TempData["Error"] = response.Error;
TempData["email"] = email;
return RedirectToAction("Index", "Home");
}
//Type cast required but we know response will be of known type
LoginResponse login = response.Result;
//Generate User Session
if (login.error != null)
{
TempData["Error"] = login.error_description;
TempData["email"] = email;
return RedirectToAction("Index", "Home");
}
UserModel user = new UserModel{
EMail = email,
UserToken = new TokenModel{
TokenValue = login.access_token,
Expiration = DateTime.UtcNow.AddSeconds(login.expires_in)
}
};
//Using Session Extensions (Store the user session)
HttpContext.Session.SetObject("User", user);
return RedirectToAction("Index", "App");
}
public IActionResult Logout(){
HttpContext.Session.SetObject("User", null);
return RedirectToAction("Index", "Home");
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]

View File

@ -4,9 +4,5 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1"/>
<PackageReference Include="MySql.Data" Version="*"/>
<PackageReference Include="MongoDB.Driver" Version="*"/>
<PackageReference Include="MongoDB.Bson" Version="*"/>
<PackageReference Include="libmetar" Version="*"/>
</ItemGroup>
</Project>

View File

@ -1,32 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using libmetar.Services;
namespace EFB.Metar
{
public static class Metar
{
private static MetarService metarService { get; set; } = new MetarService();
private static TafService tafService { get; set; } = new TafService();
public static async Task<string> GetMETAR(string ICAO){
return (await metarService.GetRawAsync(ICAO)).Raw;
}
public static async Task<List<string>> GetTAF(string ICAO){
var downloadedTAF = (await tafService.GetRawAsync(ICAO)).RawSplit;
List<string> TAF = new List<string>();
foreach (var line in downloadedTAF)
{
TAF.Add(line);
}
return TAF;
}
}
}

View File

@ -1,97 +0,0 @@
using System;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Generic;
using System.Text;
using System.Net.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using EFB.Models;
using EFB.Models.JSON;
using EFB.Sessions;
using EFB.Controllers.Form;
using EFB.Controllers.API;
namespace EFB.Models
{
public class ChartModel
{
public string ICAO { get; set; }
public Chart[] General { get; set; }
public Chart[] TextualData { get; set; }
public Chart[] GroundLayout { get; set; }
public Chart[] SID { get; set; }
public Chart[] STAR { get; set; }
public Chart[] Approach { get; set; }
public Chart[] Transition { get; set; }
public Chart[] PilotBriefing { get; set; }
[JsonConstructor]
public ChartModel(){
//Empty constructor for JSON Serialisation Purposes
}
public ChartModel(string ICAO, ChartList response)
{
this.ICAO = ICAO;
General = FillChart(response.General);
TextualData = FillChart(response.TextualData);
GroundLayout = FillChart(response.GroundLayout);
SID = FillChart(response.SID);
STAR = FillChart(response.STAR);
Approach = FillChart(response.Approach);
Transition = FillChart(response.Transition);
PilotBriefing = FillChart(response.PilotBriefing);
}
private Chart[] FillChart(ChartsCollection collection){
if (collection != null)
{
return collection.Charts;
}
return new Chart[]{};
}
public static async Task<ChartList> FetchAsync(string ICAO){
Console.WriteLine("Start");
if (FormAuthenticator.ValidateICAOCode(ICAO))
{
APIInterface API = new APIInterface();
Dictionary <string, string> headerData = new Dictionary<string, string>();
headerData.Add("referer", "luke-else.co.uk");
Dictionary<string, string> formData = new Dictionary<string, string>();
formData.Add("token", Environment.GetEnvironmentVariable("ChartFoxAPIKey", EnvironmentVariableTarget.User));
FormUrlEncodedContent body = new FormUrlEncodedContent(formData);
//make Charts request
var requestCharts = await API.Post<ChartResponse>($"https://chartfox.org/api/charts/grouped/{ICAO}", headerData, body);
Console.WriteLine("End");
if (requestCharts.Result.Status == "success")
{
return requestCharts.Result.Response;
}
}
return null;
}
}
public class Pinned
{
public Chart[] Charts { get; set; }
}
// public class Chart *Found in Models/JSON*
// {
// public string Name { get; set; }
// public string Identifier { get; set; }
// public int TypeCode { get; set; }
// public string Type { get; set; }
// public string Runway { get; set; }
// public string PseudoURL { get; set; }
// public string URL { get; set; }
// }
}

View File

@ -1,19 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EFB.Models.Route;
namespace EFB.Models
{
public class FlightsimModel
{
public SimPositionModel CurrentPosition { get; set; }
public IWaypoint Closest { get; set; }
public FlightsimModel(SimPositionModel position, IWaypoint closest)
{
CurrentPosition = position;
Closest = closest;
}
}
}

View File

@ -1,64 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace EFB.Models.JSON
{
public class ChartResponse
{
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("charts")]
public ChartList Response { get; set; }
}
public class ChartList
{
[JsonProperty("0")]
public ChartsCollection General { get; set; }
[JsonProperty("1")]
public ChartsCollection TextualData { get; set; }
[JsonProperty("2")]
public ChartsCollection GroundLayout { get; set; }
[JsonProperty("6")]
public ChartsCollection SID { get; set; }
[JsonProperty("7")]
public ChartsCollection STAR { get; set; }
[JsonProperty("8")]
public ChartsCollection Approach { get; set; }
[JsonProperty("9")]
public ChartsCollection Transition { get; set; }
[JsonProperty("99")]
public ChartsCollection PilotBriefing { get; set; }
}
public class ChartsCollection
{
[JsonProperty("group_name")]
public string Category { get; set; }
[JsonProperty("charts")]
public Chart[] Charts { get; set; }
}
public class Chart
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("identifier")]
public string Identifier { get; set; }
[JsonProperty("type_code")]
public int TypeCode { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("runway")]
public string Runway { get; set; }
[JsonProperty("pseudo_url")]
public string PseudoURL { get; set; }
[JsonProperty("url")]
public string URL { get; set; }
}
}

View File

@ -1,148 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Mvc;
using EFB.Sessions;
namespace EFB.Models
{
public class NavdataModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public int? Frequency { get; set; }
public string Latitude { get; set; }
public string Longitude { get; set; }
public NavdataModel(int id, string name, string type, string latitude, string longitude){
Id = id;
Name = name;
Type = type;
Frequency = null;
Latitude = latitude;
Longitude = longitude;
}
[JsonConstructor]
public NavdataModel(int id, string name, string type, int? frequency, string latitude, string longitude){
Id = id;
Name = name;
Type = type;
Frequency = frequency;
Latitude = latitude;
Longitude = longitude;
}
public static async Task<NavdataModel[]> Populate(){
string password = Environment.GetEnvironmentVariable("MySQLPassword", EnvironmentVariableTarget.User);
MySqlConnection con = new MySqlConnection($"server=server.luke-else.co.uk;userid=root;password={password};database=EFB");
con.Open();
// Console.WriteLine($"MySQL version : {con.ServerVersion}");
string query = "SELECT * FROM waypoints";
MySqlCommand command = new MySqlCommand(query, con);
MySqlDataReader reader = (MySqlDataReader) await command.ExecuteReaderAsync();
List<NavdataModel> navdata = new List<NavdataModel>();
while (reader.Read())
{
int id = reader.GetInt32("id");
string name = reader.GetString("name");
string type = reader.GetString("type");
string latitude = reader.GetString("latitude");
string longitude = reader.GetString("longitude");
if (type == "VOR" || type == "NDB")
{
// int? frequency = reader.GetInt32(3);
int? frequency = null;
navdata.Add(
new NavdataModel(id, name, type, frequency, latitude, longitude)
);
}else{
navdata.Add(
new NavdataModel(id, name, type, latitude, longitude)
);
}
}
return navdata.ToArray<NavdataModel>();
}
public static NavdataModel BinarySearch(ref NavdataModel[] data, int start, int end, string target){
int midpoint = start + ((end - start) / 2);
target = target.ToUpper().Trim();
string mid = data[midpoint].Name;
if (start == end-1)
{
if (mid == target)
{
return data[midpoint];
}
return null;
}
if (String.Compare(target, mid) < 0)
{
return BinarySearch(ref data, start, midpoint, target);
}
return BinarySearch(ref data, midpoint, end, target);
}
public static NavdataModel[] MergeSort(ref NavdataModel[] data, int start, int end)
{
if (start == end)
{//If we have narrowed it down to a single Item
return new NavdataModel[] { data[start] };
}
int midpoint = start + ((end - start) / 2);
//Split the data down to the left and the right portions
NavdataModel[] left = MergeSort(ref data, start, midpoint);
NavdataModel[] right = MergeSort(ref data, midpoint+1, end);
List<NavdataModel> combined = new List<NavdataModel>();
int leftPointer = 0;
int rightPointer = 0;
while (leftPointer <= left.Length-1 || rightPointer <= right.Length-1)
{
if (leftPointer == left.Length)
{//Take a value only from the right (left pointer had reached the end)
AddValue(ref combined, right[rightPointer], ref rightPointer);
}else if (rightPointer == right.Length)
{//Take a value only from the left (right pointer has reached the end)
AddValue(ref combined, left[leftPointer], ref leftPointer);
}else{
if (String.Compare(left[leftPointer].Name, right[rightPointer].Name) <= 0)
{//Take a value from the left hand side of the list. (Left value is considered 'smaller')
AddValue(ref combined, left[leftPointer], ref leftPointer);
}else{//Take a value from the right (right value is considered smaller)
AddValue(ref combined, right[rightPointer], ref rightPointer);
}
}
}
return combined.ToArray();
}
private static void AddValue(ref List<NavdataModel> data, NavdataModel value, ref int pointer){
pointer++;
data.Add(value);
}
}
}

View File

@ -8,8 +8,8 @@ namespace EFB.Models.Route
public interface IWaypoint
{
public string Name { get; set; }
public float Longitude { get; set; }
public float Latitude { get; set; }
public string Longitude { get; set; }
public string Latitude { get; set; }
public string Airway { get; set; }
public IWaypoint Next { get; set; }

View File

@ -8,8 +8,8 @@ namespace EFB.Models.Route
public class NavaidModel:IWaypoint
{
public string Name { get; set; }
public float Longitude { get; set; }
public float Latitude { get; set; }
public string Longitude { get; set; }
public string Latitude { get; set; }
public int Frequency { get; set; }
public string Airway { get; set; }
@ -17,11 +17,9 @@ namespace EFB.Models.Route
public IWaypoint Previous { get; set; } = null;
public bool Visited { get; set; } = false;
public NavaidModel(string name, string airway, float longitude, float latitude){
public NavaidModel(string name, string airway){
Name = name;
Airway = airway;
Longitude = longitude;
Latitude = latitude;
}
}
}

View File

@ -8,19 +8,17 @@ namespace EFB.Models.Route
public class WaypointModel:IWaypoint
{
public string Name { get; set; }
public float Longitude { get; set; }
public float Latitude { get; set; }
public string Longitude { get; set; }
public string Latitude { get; set; }
public string Airway { get; set; }
public IWaypoint Next { get; set; } = null;
public IWaypoint Previous { get; set; } = null;
public bool Visited { get; set; }
public WaypointModel(string name, string airway, float longitude, float latitude){
public WaypointModel(string name, string airway){
Name = name;
Airway = airway;
Longitude = longitude;
Latitude = latitude;
}
}

View File

@ -22,12 +22,12 @@ namespace EFB.Models
public RouteModel(string departure, string departureRoute, string arrival, string arrivalRoute, uint cruise){
if (FormAuthenticator.ValidateICAOCode(departure))
{
Departure = new WaypointModel(departure, departureRoute, 0, 0);
Departure = new WaypointModel(departure, departureRoute);
}
if (FormAuthenticator.ValidateICAOCode(arrival))
{
Arrival = new WaypointModel(arrival, arrivalRoute, 0, 0);
Arrival = new WaypointModel(arrival, arrivalRoute);
}
if (FormAuthenticator.ValidateCruiseAlt(cruise))
@ -36,25 +36,8 @@ namespace EFB.Models
}
}
public IWaypoint Next(){
if(Current.Next != null){
Current = Current.Next;
return Current;
}
return null;
}
public IWaypoint Previous(){
if(Current.Previous != null){
Current = Current.Previous;
return Current;
}
return null;
}
//Generate a route Object
public static async Task<RouteModel> StringToRoute(string departure, string arrival, uint cruise, string routeString){
var navdataFetch = NavdataModel.Populate();
public static RouteModel StringToRoute(string departure, string arrival, uint cruise, string routeString){
string[] routeTemp = routeString.Split(" ");
//Set departure and arrival route
@ -66,34 +49,17 @@ namespace EFB.Models
route.Current = route.Departure;
NavdataModel[] navdata = await navdataFetch;
navdata = NavdataModel.MergeSort(ref navdata, 0, navdata.Length - 1);
for (var i = 1; i < routeTemp.Length-1; i+=2)
{//Already used first item, continue itterating over every other item
IWaypoint next;
NavdataModel currentWaypoint = NavdataModel.BinarySearch(ref navdata, 0, navdata.Length-1, routeTemp[i]);
if (currentWaypoint == null)
{
currentWaypoint = new NavdataModel(0, routeTemp[i], null, "0", "0");
}
//Populate 'next' waypoint
if (routeTemp[i].Length > 3)
{//waypoint Type
next = new WaypointModel(
routeTemp[i],
routeTemp[i+1],
float.Parse(currentWaypoint.Longitude),
float.Parse(currentWaypoint.Latitude)
);
next = new WaypointModel(routeTemp[i], routeTemp[i+1]);
}else
{//Navaid Type
next = new NavaidModel(
routeTemp[i],
routeTemp[i+1],
float.Parse(currentWaypoint.Longitude),
float.Parse(currentWaypoint.Latitude)
);
next = new NavaidModel(routeTemp[i], routeTemp[i+1]);
}
next.Previous = route.Current;
@ -106,16 +72,7 @@ namespace EFB.Models
route.Current.Next = route.Arrival;
route.Arrival.Previous = route.Current;
route.Current = route.Departure;
//Assign departure and arrival coordinate positions
NavdataModel departureNav = NavdataModel.BinarySearch(ref navdata, 0, navdata.Length - 1, departure);
NavdataModel arrivalNav = NavdataModel.BinarySearch(ref navdata, 0, navdata.Length - 1, arrival);
route.Departure.Latitude = float.Parse(departureNav.Latitude);
route.Departure.Longitude = float.Parse(departureNav.Longitude);
route.Arrival.Latitude = float.Parse(arrivalNav.Latitude);
route.Arrival.Latitude = float.Parse(arrivalNav.Longitude);
route.Current = null;
return route;
}

View File

@ -1,53 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson;
using MongoDB.Driver;
namespace EFB.Models
{
public class SimPositionModel
{
[BsonId]
public ObjectId Id { get; set; }
public string EMail { get; set; } = "";
public DateTime LatestPacketUpdate { get; set; }
public SimPosition LatestPosition { get; set; } = null;
public SimPositionModel(string email, SimPosition position){
EMail = email;
LatestPacketUpdate = DateTime.Now;
LatestPosition = position;
}
}
public class SimPosition
{
public float Latitude { get; set; }
public float Longitude { get; set; }
public int Altitude { get; set; }
public SimPosition(float latitude, float longitude, int altitude){
Latitude = latitude;
Longitude = longitude;
Altitude = altitude;
}
//**Packet Processing not required**//
// public SimPosition(Packet[] data){
// if (data[0].Data != null)
// {
// //Use Linq to search through the packets for a given id and use that data
// Latitude = (data.Where(x => x.Id == 22).Select(x => x.Data[0]).ToArray())[0];
// Longitude = (data.Where(x => x.Id == 23).Select(x => x.Data[0]).ToArray())[0];
// Altitude = Convert.ToInt32((data.Where(x => x.Id == 24).Select(x => x.Data[0]).ToArray())[0]);
// }
// }
}
}

View File

@ -21,19 +21,9 @@ namespace EFB.Models
public TokenModel UserToken { get; set; } = null;
//Contains the most recent route generated by the user through the App
public string Departure { get; set; }
public string Route { get; set; }
public string Arrival { get; set; }
public uint Cruise { get; set; }
public RouteModel Route { get; set; } = null;
public TokenModel RouteToken { get; set; } = null;
//Contains the Departure and Arrival Charts for the user's route
public ChartModel DepartureCharts { get; set; }
public ChartModel ArrivalCharts { get; set; }
public ChartModel CurrentCharts { get; set; }
//Contains the most recently stored position of the user in the simulator
public object SimPosition { get; set; } = null;

View File

@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Razor;
using Newtonsoft.Json;
using EFB.Models.JSON;
using Microsoft.AspNetCore;
using EFB.Sessions;
namespace EFB.Models
{
public class ViewChartModel
{
public ChartModel Charts { get; set; }
public Chart Selected { get; set; }
public ViewChartModel(ChartModel current, string selected){
Charts = current;
if (selected != null)
{
Selected = JsonConvert.DeserializeObject<Chart>(selected);
}
}
}
}

View File

@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MongoDB.Driver;
using MongoDB.Bson;
using EFB.Models;
namespace EFB.MongoData
{
public class Mongo
{
//function that is responsible to getting the user's latest sim position from the MongoDB
public static async Task<SimPositionModel> GetLatestData(string email){
MongoClient client = new MongoClient(
Environment.GetEnvironmentVariable("MongoDBConnectionString", EnvironmentVariableTarget.User)
);
MongoDatabaseBase database = (MongoDatabaseBase)client.GetDatabase("EFB");
MongoCollectionBase<SimPositionModel> collection = (MongoCollectionBase<SimPositionModel>)database.GetCollection<SimPositionModel>("Simdata");
FilterDefinition<SimPositionModel> filter = Builders<SimPositionModel>.Filter.Eq(x => x.EMail, email);
var data = await collection.FindAsync<SimPositionModel>(filter).Result.ToListAsync();
if (data.Count > 0)
{
return data[0];
}
return null;
}
}
}

View File

@ -7,11 +7,7 @@ namespace EFB.Sessions
{
public static void SetObject(this ISession session, string key, object value)
{//Sets the object of a session to Object
session.SetString(key, JsonConvert.SerializeObject(value, Formatting.None,
new JsonSerializerSettings(){
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
}
));
session.SetString(key, JsonConvert.SerializeObject(value));
}
public static T GetObject<T>(this ISession session, string key)

View File

@ -54,12 +54,6 @@ namespace EFB
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
// endpoints.MapControllerRoute(
// name: "Navdata",
// pattern: "{controller=Navdata}/{action=Index}/{identifier?}");
// endpoints.MapControllerRoute(
// name: "Charts",
// pattern: "{controller=Charts}/{action=Index}/{ICAO?}");
});
}
}

View File

@ -1,48 +0,0 @@
@using EFB.Metar;
@model EFB.Models.UserModel;
@{
ViewData["Title"] = "Welcome";
}
<div class="row d-flex">
<div class="card-body col-md-12 bg-primary">
<div class="container jumbotron">
<h3>Current Session - @Model.EMail</h3>
<br />
<br />
<div class="row d-flex">
<div class="col-md-6">
<h4>Departure</h4>
@Model.Departure
<br />
@await Metar.GetMETAR(Model.Departure)
<h4>Cruise</h4>
@Model.Cruise ft
</div>
<div class="col-md-6">
<h4>Arrival</h4>
@Model.Arrival
<br />
@await Metar.GetMETAR(Model.Arrival)
</div>
</div>
<br />
<h4>Route</h4>
@Model.Route
</div>
</div>
</div>

View File

@ -1,37 +0,0 @@
@{
ViewData["Title"] = "Welcome";
}
<div class="row d-flex justify-content-center">
<div class="card-body col-md-6">
<div class="container jumbotron">
<h3>Chart Lookup</h3>
<br />
<br />
<form asp-controller="Charts" asp-action="Index">
<div class="form-group">
<input type="text" class="form-control" placeholder="ICAO Code" name="ICAO" value="@TempData["ICAO"]">
</div>
<button type="submit" class="btn btn-secondary">Search</button>
@{
if (TempData["Error"] != null)
{//If an error has been flagged, information will be displayed to the user
<br />
<br />
<div class="alert alert-danger">
<strong>Warning!</strong> @TempData["Error"] <button type='button' class='close' data-dismiss='alert' aria-hidden='true' />&times;
</div>
}
}
</form>
</div>
</div>
</div>

View File

@ -1,109 +0,0 @@
@using Newtonsoft.Json;
@using EFB.Metar;
@model EFB.Models.ViewChartModel;
@{
ViewData["Title"] = "Welcome";
}
<div class="row d-flex justify-content-center">
<div class="card-body col-md-4">
<div class="container jumbotron">
<form asp-controller="Charts" asp-action="Index">
<div class="form-group">
<input type="text" class="form-control" placeholder="ICAO Code" name="ICAO" value="@TempData["ICAO"]">
</div>
<button type="submit" class="btn btn-secondary">Search</button>
@{
if (TempData["Error"] != null)
{//If an error has been flagged, information will be displayed to the user
<br />
<br />
<div class="alert alert-danger">
<strong>Warning!</strong> @TempData["Error"] <button type='button' class='close' data-dismiss='alert' aria-hidden='true' />&times;
</div>
}
}
</form>
@{
<br />
<h4>Charts for: @Model.Charts.ICAO</h4>
<form asp-action="ViewCharts" method="post">
<div class="form-group">
<label>Select Charts</label><br />
<select name="chart" class="form-control">
@if (Model.Charts != null) {
<option value=""></option>
foreach(var item in Model.Charts.GroundLayout) {
var itemString = JsonConvert.SerializeObject(item);
<option value="@itemString">@item.Name</option>
}
<option value=""></option>
foreach(var item in Model.Charts.SID) {
var itemString = JsonConvert.SerializeObject(item);
<option value="@itemString">@item.Name</option>
}
<option value=""></option>
foreach(var item in Model.Charts.STAR) {
var itemString = JsonConvert.SerializeObject(item);
<option value="@itemString">@item.Name</option>
}
<option value=""></option>
foreach(var item in Model.Charts.Approach) {
var itemString = JsonConvert.SerializeObject(item);
<option value="@itemString">@item.Name</option>
}
<option value=""></option>
foreach(var item in Model.Charts.TextualData) {
var itemString = JsonConvert.SerializeObject(item);
<option value="@itemString">@item.Name</option>
}
}
</select>
<button type="submit" class="btn btn-primary">View</button>
</div>
</form>
}
<br />
<h4>Current Weather</h4>
@await Metar.GetMETAR(@Model.Charts.ICAO);
</div>
</div>
<div class="card-body col-md-8 vh-80">
<div class="container jumbotron vh-100">
@{
if (Model.Selected != null)
{
<h3>@Model.Selected.Name</h3>
<br />
<br />
<iframe src="@Model.Selected.URL" width="100%" height="90%"></iframe>
}
}
</div>
</div>
</div>

View File

@ -1,53 +0,0 @@
@model EFB.Models.FlightsimModel;
@{
ViewData["Title"] = "Welcome";
}
<div class="row d-flex">
<div class="card-body col-md-6 bg-primary">
<div class="container jumbotron">
<h3>Current Position</h3>
<br />
<br />
<h5 style="color: gray;">Last Updated at: @Model.CurrentPosition.LatestPacketUpdate.ToString()</h5>
<div class="row d-flex">
<div class="col-md-6">
<h4>Latitude</h4>
@Model.CurrentPosition.LatestPosition.Latitude
<h4>Longitude</h4>
@Model.CurrentPosition.LatestPosition.Longitude
</div>
<div class="col-md-6">
<h4>Altitude</h4>
@Model.CurrentPosition.LatestPosition.Altitude ft
</div>
</div>
</div>
</div>
<div class="card-body col-md-6 bg-success">
<div class="container jumbotron">
<h3>Closest Waypoint</h3>
<br />
<br />
<h4>@Model.Closest.Name -> @Model.Closest.Airway</h4>
<h4>Latitude</h4>
@Model.Closest.Latitude
<h4>Longitude</h4>
@Model.Closest.Longitude
</div>
</div>
</div>

View File

@ -1,63 +0,0 @@
@model EFB.Models.NavdataModel
@{
ViewData["Title"] = "Welcome";
}
<div class="row d-flex justify-content-center">
<div class="card-body col-md-6">
<div class="container jumbotron">
<h3>Navdata Lookup</h3>
<br />
<br />
<form asp-controller="Navdata" asp-action="Index">
<div class="form-group">
<input type="text" class="form-control" placeholder="Identifier" name="identifier" value="@TempData["identifier"]">
</div>
<button type="submit" class="btn btn-secondary">Search</button>
@{
if (TempData["Error"] != null)
{//If an error has been flagged, information will be displayed to the user
<br />
<br />
<div class="alert alert-danger">
<strong>Warning!</strong> @TempData["Error"] <button type='button' class='close' data-dismiss='alert' aria-hidden='true' />&times;
</div>
}
}
</form>
</div>
</div>
@{
if(Model != null){
<div class="card-body bg-warning col-md-6">
<div class="container jumbotron">
<h3>@Model.Name (@Model.Type) [@Model.Id]</h3>
<br />
<h4>Latitude</h4>
@Model.Latitude
<h4>Longitude</h4>
@Model.Longitude
@{
if(Model.Frequency != null){
<h4>Frequency</h4>
@Model.Frequency
}
}
</div>
</div>
}
}
</div>

View File

@ -1,8 +1,4 @@
@using Microsoft.AspNetCore.Http;
@using Microsoft.AspNetCore.Mvc;
@using EFB.Sessions;
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
@ -25,34 +21,7 @@
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Route" asp-action="Index">Route</a>
</li>
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Navdata" asp-action="Index">Navdata</a>
</li>
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Charts" asp-action="Index">Charts</a>
</li>
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Flightsim" asp-action="Index">FlightSim</a>
</li>
@{
UserModel user = Context.Session.GetObject<UserModel>("User");
if (user != null && user.UserToken.TokenValue != null)
{
<div class="ml-auto">
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="User" asp-action="Logout">Logout (@user.EMail)</a>
</li>
</div>
}
}
</ul>
</div>
</div>
</nav>