using System; using System.Collections.Generic; using System.Text; using System.Data; using System.ComponentModel; using System.Diagnostics; using bsmd.AISService.AIS; namespace bsmd.AISService.DB { public class AISStaticData { 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"; #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 int? Save(AIS_Target target, DBConnector con, AISStation aisStation) { if(target.LastStaticData == null) return null; int mmsi = -1; int id = -1; 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 = Convert.ToInt32(result); } #region Class A if (target.LastStaticData is AIS_StaticData) { AIS_StaticData staticData = target.LastStaticData as AIS_StaticData; if (id >= 0) { if (staticData.ETA.HasValue) { query = string.Format("UPDATE aisstaticdata SET imonumber={0}, callsign='{1}', name='{2}', shiptype={3}, typeofdevice='{4}', shipdescription='{5}', eta='{6}', destination='{7}', breadth={8}, length={9}, draught='{10}', stationid={11}, classb=0 WHERE id={12}", staticData.IMONumber, staticData.Callsign.Replace("'","''"), staticData.Name.Replace("'", "''"), staticData.ShipTypeVal, staticData.DeviceName, staticData.ShipType, staticData.DBETA, staticData.Destination.Replace("'", "''"), staticData.Breadth, staticData.Length, staticData.Draught, aisStation.Id, id); } else { query = string.Format("UPDATE aisstaticdata SET imonumber={0}, callsign='{1}', name='{2}', shiptype={3}, typeofdevice='{4}', shipdescription='{5}', destination='{6}', breadth={7}, length={8}, draught='{9}', stationid={10}, classb=0 WHERE id={11}", staticData.IMONumber, staticData.Callsign.Replace("'", "''"), staticData.Name.Replace("'", "''"), staticData.ShipTypeVal, staticData.DeviceName, staticData.ShipType, staticData.Destination.Replace("'", "''"), staticData.Breadth, staticData.Length, staticData.Draught, aisStation.Id, id); } con.ExecuteNonQuery(query); } else { if (staticData.ETA.HasValue) { query = string.Format("INSERT INTO aisstaticdata SET imonumber={0}, callsign='{1}', name='{2}', shiptype={3}, typeofdevice='{4}', shipdescription='{5}', eta='{6}', destination='{7}', breadth={8}, length={9}, draught='{10}', stationid={11}, mmsi={12}, classb=0", staticData.IMONumber, staticData.Callsign.Replace("'", "''"), staticData.Name.Replace("'", "''"), staticData.ShipTypeVal, staticData.DeviceName, staticData.ShipType, staticData.DBETA, staticData.Destination.Replace("'", "''"), staticData.Breadth, staticData.Length, staticData.Draught, aisStation.Id, staticData.MMSI); } else { query = string.Format("INSERT INTO aisstaticdata SET imonumber={0}, callsign='{1}', name='{2}', shiptype={3}, typeofdevice='{4}', shipdescription='{5}', destination='{6}', breadth={7}, length={8}, draught='{9}', stationid={10}, mmsi={11}, classb=0", staticData.IMONumber, staticData.Callsign.Replace("'", "''"), staticData.Name.Replace("'", "''"), staticData.ShipTypeVal, staticData.DeviceName, staticData.ShipType, staticData.Destination.Replace("'", "''"), staticData.Breadth, staticData.Length, staticData.Draught, aisStation.Id, staticData.MMSI); } con.ExecuteNonQuery(query); id = Convert.ToInt32(con.ExecuteScalar("SELECT LAST_INSERT_ID()")); } } #endregion #region Class B if (target.LastStaticData is AIS_ClassBStatic) { AIS_ClassBStatic staticData = target.LastStaticData as AIS_ClassBStatic; if (id >= 0) // Update { query = string.Format("UPDATE aisstaticdata SET stationid={0}, shiptype={1}, classb=1", aisStation.Id, staticData.ShipTypeVal); if(staticData.Callsign != null) query += string.Format(", callsign='{0}'", staticData.Callsign); if(staticData.Name != null) query += string.Format(", name='{0}'", staticData.Name); if(staticData.VendorId != null) query += string.Format(", typeofdevice='{0}'", staticData.VendorId); if(staticData.ShipType != null) query += string.Format(", shipdescription='{0}'", staticData.ShipType); query += string.Format(" WHERE id={0}", id); con.ExecuteNonQuery(query); } else // Insert { query = string.Format("INSERT INTO aisstaticdata SET callsign='{0}', name='{1}', shiptype={2}, typeofdevice='{3}', shipdescription='{4}', stationid={5}, mmsi={6}, classb=1", staticData.Callsign, staticData.Name, staticData.ShipTypeVal, staticData.VendorId, staticData.ShipType, aisStation.Id, staticData.MMSI ); con.ExecuteNonQuery(query); id = Convert.ToInt32(con.ExecuteScalar("SELECT LAST_INSERT_ID()")); } } #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(); Trace.WriteLine(string.Format("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 } }