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("MMSI: {0}
", this.MMSI)); sb.Append(string.Format("Name: {0}
", this.Name)); sb.Append(string.Format("Latitude: {0}°
", this.LastLatitude.HasValue ? this.LastLatitude.Value.ToString("N3") : "?")); sb.Append(string.Format("Longitude: {0}°
", this.LastLongitude.HasValue ? this.LastLongitude.Value.ToString("N3") : "?")); sb.Append(string.Format("Last report: {0}
", this.LastPositionReport.HasValue ? this.LastPositionReport.Value.ToString() : "?")); sb.Append(string.Format("Type: {0} [{1}]
", this.Description, this.ShipType)); sb.Append(string.Format("Navstatus: {0}
", 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 /// /// Saves a (class A or B) position report /// /// target to save /// id of insert operation (to update hotposition table) 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 /// /// Loads shipname for display (until static data has been received) /// 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; } /// /// Loads callsign for display (until static data has been received) /// 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; } /// /// preload target with data from database until static data has been received /// /// target to load 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(); } /// /// Load all ships that have a position and static data from database /// public static List LoadDBShips(DBConnector con) { List result = new List(); 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 { 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 } }