git_bsmd/AIS/bsmd.AISService/DB/AISStaticData.cs

496 lines
19 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.ComponentModel;
using System.Diagnostics;
using bsmd.AISService.AIS;
using log4net;
namespace bsmd.AISService.DB
{
public class AISStaticData : AISBaseEntity
{
public enum DisplayStringType
{
NAME,
MMSI,
CALLSIGN
}
private const string LoadDBShipsQuery = "SELECT aisposreport.MMSI, aisposreport.timestamp, aisposreport.latitude, aisposreport.longitude, aisposreport.stationid, aisposreport.cog, aisposreport.heading, aisposreport.navstatus, aisstaticdata.callsign, aisstaticdata.name, aisstaticdata.shiptype, aisstaticdata.classb, aisstaticdata.shipdescription FROM aisstaticdata JOIN hotposition ON aisstaticdata.mmsi = hotposition.mmsi JOIN aisposreport ON aisposreport.id = hotposition.pid ORDER BY aisstaticdata.name";
private static ILog _log = LogManager.GetLogger(typeof(AISStaticData));
#region Fields
private int mmsi;
private string name;
private string callsign;
private DateTime? lastposition;
private double? lastLatitude;
private double? lastLongitude;
private int stationid;
private int navstatus;
private int shiptype;
private string shipdescription;
private int cog;
private int heading;
private bool isClassB;
private bool isWatchkeeper;
private bool isTimedOut = false;
private bool isSelected = false;
private static DisplayStringType displayStringType = DisplayStringType.NAME;
#endregion
#region Properties
public int MMSI
{
get { return this.mmsi; }
}
public string Name
{
get { return this.name; }
}
public string Callsign
{
get { return this.callsign; }
}
public DateTime? LastPositionReport
{
get { return this.lastposition; }
}
public double? LastLatitude
{
get { return this.lastLatitude; }
}
public double? LastLongitude
{
get { return this.lastLongitude; }
}
public bool IsClassB
{
get { return this.isClassB; }
}
public int ShipType
{
get { return this.shiptype; }
}
public string Description
{
get { return this.shipdescription; }
}
public bool IsWatchkeeperShip
{
get { return this.isWatchkeeper; }
set { this.isWatchkeeper = value; }
}
public int StationId
{
get { return this.stationid; }
}
public int Heading
{
get { return this.heading; }
}
public int COG
{
get { return this.cog; }
}
public int NavStatus
{
get { return this.navstatus; }
}
public bool Selected
{
get { return this.isSelected; }
set { this.isSelected = value; }
}
public static DisplayStringType DisplayStringTyp
{
get { return displayStringType; }
set { displayStringType = value; }
}
public bool IsTimedOut
{
get { return this.isTimedOut; }
set { this.isTimedOut = value; }
}
#endregion
#region public methods
public string ToHtmlString()
{
StringBuilder sb = new StringBuilder();
sb.Append(string.Format("<em>MMSI</em>: {0} <br />", this.MMSI));
sb.Append(string.Format("<em>Name</em>: <span style=\"font-size: bigger\">{0}</span><br />", this.Name));
sb.Append(string.Format("Latitude: {0}° <br />", this.LastLatitude.HasValue ? this.LastLatitude.Value.ToString("N3") : "?"));
sb.Append(string.Format("Longitude: {0}° <br />", this.LastLongitude.HasValue ? this.LastLongitude.Value.ToString("N3") : "?"));
sb.Append(string.Format("Last report: {0} <br />", this.LastPositionReport.HasValue ? this.LastPositionReport.Value.ToString() : "?"));
sb.Append(string.Format("Type: {0} [{1}]<br />", this.Description, this.ShipType));
sb.Append(string.Format("Navstatus: {0}<br />", this.NavStatus));
return sb.ToString();
}
#endregion
#region overrides
public override string ToString()
{
switch (displayStringType)
{
case DisplayStringType.NAME:
string result = "?";
if (this.name != null && this.name.Length > 0)
result = this.name;
return result;
case DisplayStringType.MMSI:
return this.mmsi.ToString();
case DisplayStringType.CALLSIGN:
if (this.Callsign == null || this.Callsign.Length == 0)
return "?";
return this.Callsign;
default:
return string.Format("{0} - {1}", this.name, this.mmsi);
}
}
#endregion
#region static methods
#region save a position report
/// <summary>
/// Saves a (class A or B) position report
/// </summary>
/// <param name="target">target to save</param>
/// <returns>id of insert operation (to update hotposition table)</returns>
public static Guid? Save(AIS_Target target, DBConnector con, AISStation aisStation)
{
if(target.LastStaticData == null) return null;
int mmsi = -1;
Guid id = Guid.Empty;
if(target.LastStaticData is AIS_StaticData) {
mmsi = ((AIS_StaticData)target.LastStaticData).MMSI;
}
if(target.LastStaticData is AIS_ClassBStatic) {
mmsi = ((AIS_ClassBStatic)target.LastStaticData).MMSI;
}
string query = string.Format("SELECT id FROM aisstaticdata WHERE mmsi={0}", mmsi);
object result = con.ExecuteScalar(query);
if (result != null) // update
{
id = (Guid) result;
}
#region Class A
if (target.LastStaticData is AIS_StaticData)
{
AIS_StaticData staticData = target.LastStaticData as AIS_StaticData;
if (id != Guid.Empty)
{
query = string.Format("UPDATE aisstaticdata SET imonumber={0}, callsign='{1}', name='{2}', shiptype={3}, dimension={4}, typeofdevice={5}, maxpresetstaticdraught={6}, " +
"destination='{7}', dte={8}, spare={9}, mmsi={10}, eta={11}, classb={12}, breadth={13}, length={14}, aisstation_id='{15}' " +
"WHERE Id='{16}'",
staticData.IMONumber,
(staticData.Callsign ?? "").Replace("'", "''"),
(staticData.Name ?? "").Replace("'", "''"),
staticData.ShipTypeVal,
staticData.DBDimension,
staticData.DBTypeOfDevice,
staticData.Draught,
(staticData.Destination ?? "").Replace("'", "''"),
staticData.DTE,
staticData.Spare,
staticData.MMSI,
staticData.ETA.HasValue ? string.Format("'{0}'", staticData.DBETA) : "NULL",
0,
staticData.Breadth,
staticData.Length,
aisStation.Id,
id);
con.ExecuteNonQuery(query);
}
else
{
id = Guid.NewGuid();
query = string.Format("INSERT INTO aisstaticdata (Id, aisversion, imoNumber, callsign, name, shiptype, dimension, typeofdevice, maxpresetstaticdraught, destination, " +
"dte, spare, mmsi, eta, classb, breadth, length, aisstation_id) VALUES ('{0}', {1}, {2}, '{3}', '{4}', {5}, {6}, {7}, {8}, '{9}', {10}, {11}, {12}, {13}, {14}, {15}, {16}, '{17}')",
id,
0,
staticData.IMONumber,
(staticData.Callsign ?? "").Replace("'", "''"),
(staticData.Name ?? "").Replace("'", "''"),
staticData.ShipTypeVal,
staticData.DBDimension,
staticData.DBTypeOfDevice,
staticData.Draught,
(staticData.Destination ?? "").Replace("'", "''"),
staticData.DTE,
staticData.Spare,
staticData.MMSI,
staticData.ETA.HasValue ? string.Format("'{0}'", staticData.DBETA) : "NULL",
0,
staticData.Breadth,
staticData.Length,
aisStation.Id.Value);
con.ExecuteNonQuery(query);
}
}
#endregion
#region Class B
if (target.LastStaticData is AIS_ClassBStatic)
{
AIS_ClassBStatic staticData = target.LastStaticData as AIS_ClassBStatic;
if (id != Guid.Empty) // Update
{
query = string.Format("UPDATE aisstaticdata SET aisstation_id = '{0}', shiptype={1}, classb=1, dimension = {2}, spare = {3}",
aisStation.Id, staticData.ShipTypeVal, staticData.Dimension, staticData.Spare);
if(staticData.Callsign != null) query += string.Format(", callsign='{0}'", staticData.Callsign.Replace("'", "''"));
if(staticData.Name != null) query += string.Format(", name='{0}'", staticData.Name.Replace("'","''"));
query += string.Format(" WHERE Id='{0}'", id);
con.ExecuteNonQuery(query);
}
else // Insert
{
id = Guid.NewGuid();
query = string.Format("INSERT INTO aisstaticdata (Id, callsign, name, shiptype, classb, dimension, spare, aisstation_id, mmsi) VALUES ('{0}', '{1}', '{2}', {3}, {4}, {5}, {6}, '{7}', {8})",
id,
(staticData.Callsign ?? "").Replace("'","''"),
(staticData.Name ?? "").Replace("'","''"),
staticData.ShipTypeVal,
1,
staticData.Dimension,
staticData.Spare,
aisStation.Id,
staticData.MMSI
);
con.ExecuteNonQuery(query);
}
}
#endregion
return id;
}
#endregion
/// <summary>
/// Loads shipname for display (until static data has been received)
/// </summary>
public static string LoadName(int mmsi, DBConnector con)
{
string query = string.Format("SELECT name FROM aisstaticdata where mmsi={0}", mmsi);
string result = con.ExecuteScalar(query) as string;
if (result == null) result = "";
return result;
}
/// <summary>
/// Loads callsign for display (until static data has been received)
/// </summary>
public static string LoadCallsign(int mmsi, DBConnector con)
{
string query = string.Format("SELECT callsign FROM aisstaticdata where mmsi={0}", mmsi);
string result = con.ExecuteScalar(query) as string;
if (result == null) result = "";
return result;
}
/// <summary>
/// preload target with data from database until static data has been received
/// </summary>
/// <param name="target">target to load</param>
public static void PreloadTarget(AIS_Target target, DBConnector con)
{
if (target.MMSI == 0) return;
string query = string.Format("SELECT name, callsign, shiptype FROM aisstaticdata where mmsi={0}", target.MMSI);
IDataReader reader = con.ExecuteQuery(query);
if (reader.Read())
{
if (!reader.IsDBNull(0)) target.LastDBName = reader.GetString(0);
if (!reader.IsDBNull(1)) target.Callsign = reader.GetString(1);
if (!reader.IsDBNull(2))
target.TargetType = AIS_StaticData.GetShipTypeSimple(reader.GetInt32(2));
}
reader.Close();
}
/// <summary>
/// Load all ships that have a position and static data from database
/// </summary>
public static List<AISStaticData> LoadDBShips(DBConnector con)
{
List<AISStaticData> result = new List<AISStaticData>();
IDataReader reader = con.ExecuteQuery(AISStaticData.LoadDBShipsQuery);
while (reader.Read())
{
AISStaticData ship = new AISStaticData();
ship.mmsi = reader.GetInt32(0);
ship.lastposition = reader.GetDateTime(1);
ship.lastLatitude = (double) Math.Round(reader.GetInt32(2) / 600000.0, 4);
ship.lastLongitude = (double) Math.Round(reader.GetInt32(3) / 600000.0, 4);
ship.stationid = reader.GetInt32(4);
ship.cog = reader.GetInt32(5);
ship.heading = reader.GetInt32(6);
ship.navstatus = reader.GetInt32(7);
if(!reader.IsDBNull(8))
ship.callsign = reader.GetString(8);
if(!reader.IsDBNull(9))
ship.name = reader.GetString(9);
ship.shiptype = reader.GetInt32(10);
if (reader.IsDBNull(11)) ship.isClassB = false;
else ship.isClassB = reader.GetBoolean(11);
ship.shipdescription = reader.GetString(12);
result.Add(ship);
}
reader.Close();
_log.InfoFormat("AISStaticData: {0} ships loaded from DB", result.Count);
return result;
}
#endregion
}
#region Comparer Class for grid
public class AISStaticData_Comparer : IComparer<AISStaticData>
{
private SortPropertyEnum sortProperty = SortPropertyEnum.NAME;
private ListSortDirection sortDirection = ListSortDirection.Ascending;
public enum SortPropertyEnum
{
NONE,
MMSI,
NAME,
CALLSIGN,
LASTUPDATE,
DESCRIPTION
}
#region Properties
public ListSortDirection SortDirection
{
get { return this.sortDirection; }
set { this.sortDirection = value; }
}
public SortPropertyEnum SortProperty
{
get { return this.sortProperty; }
set { this.sortProperty = value; }
}
#endregion
public int Compare(AISStaticData x, AISStaticData y)
{
switch (this.sortProperty)
{
case SortPropertyEnum.NONE:
return 0;
case SortPropertyEnum.NAME:
{
string xName = x.Name;
if (xName == null) xName = "";
string yName = y.Name;
if (yName == null) yName = "";
if (this.sortDirection == ListSortDirection.Ascending)
return xName.CompareTo(yName);
else
return yName.CompareTo(xName);
}
case SortPropertyEnum.LASTUPDATE:
{
DateTime xTime = x.LastPositionReport ?? DateTime.MinValue;
DateTime yTime = y.LastPositionReport ?? DateTime.MinValue;
if (this.sortDirection == ListSortDirection.Ascending)
return xTime.CompareTo(yTime);
else
return yTime.CompareTo(xTime);
}
case SortPropertyEnum.MMSI:
{
if (this.sortDirection == ListSortDirection.Ascending)
return x.MMSI.CompareTo(y.MMSI);
else
return y.MMSI.CompareTo(x.MMSI);
}
case SortPropertyEnum.CALLSIGN:
{
string xCallsign = x.Callsign;
if (xCallsign == null) xCallsign = "";
string yCallsign = y.Callsign;
if (yCallsign == null) yCallsign = "";
if (this.sortDirection == ListSortDirection.Ascending)
return xCallsign.CompareTo(yCallsign);
else
return yCallsign.CompareTo(xCallsign);
}
case SortPropertyEnum.DESCRIPTION:
{
string xDescription = x.Description;
if (xDescription == null) xDescription = "";
string yDescription = y.Description;
if (yDescription == null) yDescription = "";
if (this.sortDirection == ListSortDirection.Ascending)
return xDescription.CompareTo(yDescription);
else
return yDescription.CompareTo(xDescription);
}
default:
return 0;
}
}
#endregion
}
}