Compare commits

...

41 Commits

Author SHA1 Message Date
e783f8c614 Added metar to route page 2022-02-18 22:47:00 +00:00
c418188481 Completed app page + added metar class 2022-02-18 22:43:01 +00:00
ec5ca51602 Added double negation to clean code 2022-02-18 22:01:53 +00:00
eff67b7697 Added flight sim view 2022-02-18 21:46:00 +00:00
e271e49374 Added closest waypoint function 2022-02-18 21:13:21 +00:00
5316df08a5 Several changes - updated string to route to include coordinates - updated model for flight sim to only contain the closest point - User model now tracks route status... departure etc 2022-02-18 20:38:45 +00:00
10af903706 Added MongoDB Methods and introduced flight sim controller 2022-02-18 18:49:56 +00:00
eda71069a4 Updated user model to allow for storing of departure and arrival points 2022-02-18 18:36:10 +00:00
8be3b0fa02 Added SimPositionModel from flight tracker + setup mongo files 2022-02-18 17:18:00 +00:00
0252f115c6 Updated navdata to take table headings as opposed to index values from database 2022-02-17 20:21:50 +00:00
8ac4a3d693 Chart Viewer now complete 2022-02-15 16:03:46 +00:00
39cc7caef7 Tried sending model back to controller but now unsure of how to do so 2022-02-11 20:55:53 +00:00
a4e7a30a9f Force user to be logged in before accessing routes 2022-02-11 20:14:57 +00:00
d8a40e64ef Adapted ChartModel to accept an ICAO Code 2022-02-11 19:54:11 +00:00
0c68d05af1 Added Current Chart to user model 2022-02-11 19:41:46 +00:00
dd2a367a58 Added and Started on views for Chart Viewer 2022-02-11 19:40:31 +00:00
76878e7745 Updated Chart Fetch functions in order to create a more generic template 2022-02-11 17:00:08 +00:00
35a6686cd5 Updated layout to use EMail when logged in instead of API Token 2022-02-09 20:48:10 +00:00
39c18ee9bf Updated NavdataModel and RouteController to user environment Variables 2022-02-09 20:41:39 +00:00
30ac25c8fb Added addition constructor for JSON Serialisation 2022-02-09 20:40:24 +00:00
c3a414285a Update Route Controller to ensure that response is valid before parsin 2022-02-09 20:22:46 +00:00
b6e5f09c11 Add Update route controller to fetch charts and adapt model to allow for response parsing 2022-02-09 20:19:32 +00:00
21aff4096f Altered user model and updated controller to make Chart requests on load 2022-02-09 19:08:56 +00:00
94393e232c Altered API Interface import 2022-02-09 18:11:00 +00:00
b2d4b52d6e Added Provisional Chart Models 2022-02-09 17:59:02 +00:00
6887d33fe2 Add logout feature 2022-02-07 20:58:32 +00:00
0cf2360576 Updated Navdata view 2022-02-07 20:25:28 +00:00
5a49e270b9 Updated Navbar Layout 2022-02-07 20:00:51 +00:00
58eef9ea67 Added Navdata View (Needs Tweaking) 2022-02-01 20:25:31 +00:00
ef4d44d7d2 Added MergeSort Function for Navdata 2022-01-31 22:50:09 +00:00
c41f19811f Added Binary Search to Navdata 2022-01-31 15:59:44 +00:00
cd488440b9 Updated Populate Method to get data from DB
Runs extremely quickly ~150ms on my system in debug mode (10,000 records)
2022-01-31 15:07:16 +00:00
f0da93cdae Updated route controller to go through every response from the server to avoid missing a key item 2022-01-31 14:29:09 +00:00
9e00882743 Updated Route controller to adapt to new model 2022-01-31 14:23:23 +00:00
334ad6bce5 Altered user Model to allow for pure string value as oposed to object 2022-01-31 12:10:06 +00:00
3cb2b9c9b5 Updated Session extensions and Route Contoller
Increased the number of Poll requests and disabled an irrelevant error stating that there was a cyclical struture (Just a Doubly Linked List)
2022-01-27 09:46:38 +00:00
924e25e1c6 Update NavdataModel.cs 2022-01-26 13:34:49 +00:00
b68cc2ac3f Created NavData Model
Create Navdata Model and add Navata controller (Currently empty)
2022-01-26 13:11:04 +00:00
87a5dbfafa
Merge pull request #14 from Flight-Simulator-EFB/feature/route
Feature/route
2022-01-11 18:46:35 +00:00
74b5f0cf0c Added Next & Previous Methods to Route 2022-01-11 18:44:04 +00:00
cea0b0e32e Added Next & Previous Methods to route 2022-01-11 18:43:08 +00:00
28 changed files with 1306 additions and 188 deletions

View File

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

View File

@ -0,0 +1,76 @@
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

@ -0,0 +1,87 @@
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

@ -0,0 +1,56 @@
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,134 +46,150 @@ namespace EFB.Controllers
public async Task<IActionResult> New(string departure, string arrival, string cruise) public async Task<IActionResult> New(string departure, string arrival, string cruise)
{ {
UserModel user = HttpContext.Session.GetObject<UserModel>("User"); 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 {//If the user is still authenticated
if (FormAuthenticator.ValidateICAOCode(departure) && FormAuthenticator.ValidateICAOCode(arrival)) return RedirectToAction("Index", "Home");
{//If the user has entered valid ICAOs }
uint cruiseAlt; 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;
if (uint.TryParse(cruise, out cruiseAlt) && FormAuthenticator.ValidateCruiseAlt(cruiseAlt)) if (uint.TryParse(cruise, out cruiseAlt) && FormAuthenticator.ValidateCruiseAlt(cruiseAlt))
{//If the cruise altitude if within limits. {//If the cruise altitude if within limits.
//Submit route request... //Submit route request...
APIInterface API = new APIInterface(); APIInterface API = new APIInterface();
//Prepare data to be send off with request (route) //Prepare data to be send off with request (route)
Dictionary<string, string> headerData = new Dictionary<string, string>(); Dictionary<string, string> headerData = new Dictionary<string, string>();
headerData.Add("Authorization", $"Bearer {user.UserToken.TokenValue}"); headerData.Add("Authorization", $"Bearer {user.UserToken.TokenValue}");
RouteRequest routeRequest = new RouteRequest() RouteRequest routeRequest = new RouteRequest()
{ {
departure = departure, departure = departure,
destination = arrival, destination = arrival,
preferredminlevel = cruiseAlt / 1000, preferredminlevel = cruiseAlt / 1000,
preferredmaxlevel = cruiseAlt / 1000, preferredmaxlevel = cruiseAlt / 1000,
}; };
StringContent content = new StringContent(JsonConvert.SerializeObject(routeRequest), Encoding.UTF8, "application/json"); 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 ResponseModel<string> responseRoute = await requestRoute;
var requestRoute = API.Post<string>("https://api.autorouter.aero/v1.0/router", headerData, content);
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) user.RouteToken = routeToken;
{//Update User session and add route ID HttpContext.Session.SetObject("User", user);
TokenModel routeToken = new TokenModel()
{
TokenValue = responseRoute.Result.ToString()
};
user.RouteToken = routeToken; return await Poll(departure, arrival, cruiseAlt);
HttpContext.Session.SetObject("User", user);
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"] = "Invalid Departure or Arrival ICAO";
TempData["Error"] = responseRoute.Error;
return RedirectToAction("Index", "Route"); return RedirectToAction("Index", "Route");
} }
return RedirectToAction("Index", "Home"); TempData["Error"] = "Invalid Cruise Altitude";
TempData["Departure"] = departure;
TempData["Arrival"] = arrival;
return RedirectToAction("Index", "Route");
} }
public async Task<IActionResult> Poll(string departure, string arrival, uint cruise) public async Task<IActionResult> Poll(string departure, string arrival, uint cruise)
{ {
if (HttpContext.Session.GetString("User") != null) if (HttpContext.Session.GetString("User") == null)
{//If the user is currently logged in {//If the user is not currently logged in
UserModel user = HttpContext.Session.GetObject<UserModel>("User"); TempData["Error"] = "Please login before trying to plan a route";
if (user.RouteToken != null)
{//If the user has a route object (e.g, they have been to the route page)
//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>();
headerData.Add("Authorization", $"Bearer {user.UserToken.TokenValue}");
while (collected == false && pollCount < 3)
{
//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");
}
}
else
{
return RedirectToAction("Index", "Route"); return RedirectToAction("Index", "Route");
} }
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)
return RedirectToAction("Index", "Route");
}
//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>();
/*-----Chart Fetching Operations--------*/
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")
{
collected = true;
routeString = item.FlightPlan;
break;
}
}
Thread.Sleep(3000);
pollCount++;
}
if (collected)
{
//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");
}
TempData["Error"] = $"Unable to get route after {pollCount} Attempts!";
return RedirectToAction("Index", "Route");
} }

View File

@ -9,6 +9,7 @@ using EFB.Models.JSON;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using EFB.Models; using EFB.Models;
using EFB.Sessions; using EFB.Sessions;
using EFB.Controllers.API;
namespace EFB.Controllers namespace EFB.Controllers
{ {
@ -30,63 +31,63 @@ namespace EFB.Controllers
public async Task<IActionResult> Login(string email, string password){ 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"; TempData["Error"] = "Please enter a valid E-Mail";
return RedirectToAction("Index", "Home"); 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)] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]

View File

@ -4,5 +4,9 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1"/> <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> </ItemGroup>
</Project> </Project>

32
Metar/Metar.cs Normal file
View File

@ -0,0 +1,32 @@
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;
}
}
}

97
Models/ChartModel.cs Normal file
View File

@ -0,0 +1,97 @@
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; }
// }
}

19
Models/FlightsimModel.cs Normal file
View File

@ -0,0 +1,19 @@
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

@ -0,0 +1,64 @@
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; }
}
}

148
Models/NavdataModel.cs Normal file
View File

@ -0,0 +1,148 @@
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 interface IWaypoint
{ {
public string Name { get; set; } public string Name { get; set; }
public string Longitude { get; set; } public float Longitude { get; set; }
public string Latitude { get; set; } public float Latitude { get; set; }
public string Airway { get; set; } public string Airway { get; set; }
public IWaypoint Next { get; set; } public IWaypoint Next { get; set; }

View File

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

View File

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

View File

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

View File

@ -0,0 +1,53 @@
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,9 +21,19 @@ namespace EFB.Models
public TokenModel UserToken { get; set; } = null; public TokenModel UserToken { get; set; } = null;
//Contains the most recent route generated by the user through the App //Contains the most recent route generated by the user through the App
public RouteModel Route { get; set; } = null; public string Departure { get; set; }
public string Route { get; set; }
public string Arrival { get; set; }
public uint Cruise { get; set; }
public TokenModel RouteToken { 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 //Contains the most recently stored position of the user in the simulator
public object SimPosition { get; set; } = null; public object SimPosition { get; set; } = null;

28
Models/ViewChartModel.cs Normal file
View File

@ -0,0 +1,28 @@
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);
}
}
}
}

30
Mongo/Mongo.cs Normal file
View File

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

View File

@ -54,6 +54,12 @@ namespace EFB
endpoints.MapControllerRoute( endpoints.MapControllerRoute(
name: "default", name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}"); 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?}");
}); });
} }
} }

48
Views/App/Index.cshtml Normal file
View File

@ -0,0 +1,48 @@
@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>

37
Views/Charts/Index.cshtml Normal file
View File

@ -0,0 +1,37 @@
@{
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

@ -0,0 +1,109 @@
@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

@ -0,0 +1,53 @@
@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

@ -0,0 +1,63 @@
@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,4 +1,8 @@
<!DOCTYPE html> @using Microsoft.AspNetCore.Http;
@using Microsoft.AspNetCore.Mvc;
@using EFB.Sessions;
<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
@ -21,7 +25,34 @@
<li class="nav-item"> <li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Index">Home</a> <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li> </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> </ul>
</div> </div>
</div> </div>
</nav> </nav>