/// <summary> /// Creates a new <see cref="Station"/> instance, and adds it the specified <see cref="Star"/>. If an object /// already exists in this star with the same name, it will be turned into a station. /// </summary> /// <param name="name">The name of the new station</param> /// <param name="star">The star system the new station belongs to</param> /// <returns>The newly created station</returns> /// <exception cref="ArgumentNullException">The provided name or container is null.</exception> /// <exception cref="ArgumentException">The provided name is already in use.</exception> public static AstronomicalObject CreateStation(string name, AstronomicalObject star) { if (name == null) { throw new ArgumentNullException("name"); } if (star == null) { throw new ArgumentException("star"); } AstronomicalObject result = star.Environment.FindObjectByName(name); if (result == null) { result = new AstronomicalObject(name, star.Environment, AstronomicalObjectType.Station, star); } else { result.Star = star; result.Type = AstronomicalObjectType.Station; } return(result); }
/// <summary> /// Creates a new <see cref="Star"/> instance and adds it into this environment /// </summary> /// <param name="name">The name of the new star system</param> /// <param name="env">The environment that will contain the new star</param> /// <returns>The created <see cref="Star"/> instance.</returns> /// <exception cref="ArgumentNullException">The provided name is null</exception> /// <exception cref="ArgumentException">The provided name is already used by an existing star</exception> public static AstronomicalObject CreateStar(string name, EliteEnvironment env) { if (name == null) { throw new ArgumentNullException("name"); } if (env == null) { throw new ArgumentNullException("name"); } AstronomicalObject result = null; AstronomicalObject existing = env.FindObjectByName(name); if (existing != null) { existing.Star = existing; existing.Type = AstronomicalObjectType.Star; result = existing; } else { result = new AstronomicalObject(name, env, AstronomicalObjectType.Star, null); result.Star = result; } return(result); }
/// <summary> /// Returns a list of possible commodities that can be bought in this station and sold in another specified station. /// </summary> /// <param name="otherStation">A station to sell at</param> /// <returns>A list of <see cref="TradeJumpData"/> instances, describing the available trading options</returns> /// <exception cref="ArgumentNullException">The <paramref name="otherStation"/> parameter is null</exception> /// <exception cref="ArgumentException">The <paramref name="otherStation"/> parameter equals the current station</exception> public List <TradeJumpData> FindTradesWith(AstronomicalObject otherStation) { if (otherStation == null) { throw new ArgumentNullException("otherStation"); } if (otherStation == this) { throw new ArgumentException("The otherStation argument cannot contain the Station you call the method on.", "otherStation"); } List <TradeJumpData> result = new List <TradeJumpData>(); foreach (Trade t in Trades) { if (!t.CanSell) { continue; } Trade t2 = otherStation.FindCommodity(t.Commodity); if (t2 == null || !t2.CanBuy) { continue; } result.Add(new TradeJumpData(t, t2)); } return(result); }
/// <summary> /// Computes the most profitable trading jump given the specified constraints /// </summary> /// <param name="from">The <see cref="Station"/> to buy the goods from</param> /// <param name="to">The <see cref="Station"/> to sell the goods at</param> /// <param name="cargo">The maximum amount of units that can be bought</param> /// <param name="budget">The maximum price that can be paid for buying the goods</param> /// <returns>A <see cref="TradeJumpData"/> instance describing the ideal trade operation</returns> /// <exception cref="ArgumentNullException">The <paramref name="from"/> or <paramref name="to"/> arguments are null.</exception> /// <exception cref="ArgumentOutOfRangeException"> /// <list type="bullet"> /// <item> /// <description>The <paramref name="cargo"/> parameter is negative or zero.</description> /// </item> /// <item> /// <description>The <paramref name="budget"/> parameter is negative or zero.</description> /// </item> /// </list> /// </exception> /// <exception cref="ArgumentException">The <paramref name="from"/> and <paramref name="to"/> parameters are equal</exception> public TradeJumpData FindBestProfit(AstronomicalObject from, AstronomicalObject to, int cargo, int budget) { if (from == null) { throw new ArgumentNullException("from"); } if (to == null) { throw new ArgumentNullException("to"); } if (from == to) { throw new ArgumentException("The from and to stations cannot be the same"); } if (cargo <= 0) { throw new ArgumentOutOfRangeException("cargo"); } if (budget <= 0) { throw new ArgumentOutOfRangeException("budget"); } TradeJumpData result = new TradeJumpData(); result.TotalProfit = Single.MinValue; foreach (Trade t in from.Trades) { if (!t.CanSell) { continue; } Trade t2 = to.FindCommodity(t.Commodity); if (t2 == null || !t2.CanBuy) { continue; } float profitPerUnit = t2.BuyingPrice - t.SellingPrice; int cargoSize = Math.Min(cargo, (int)(budget / t.SellingPrice)); float totalProfit = profitPerUnit * cargoSize; if (totalProfit > result.TotalProfit) { result.Fill(t, t2, cargoSize); } } if (result.Commodity == null) { return(null); } return(result); }
/// <summary> /// Returns the <see cref="AstronomicalObject"/> singleton that is used to represent deep space locations, /// moving it to the specified star /// </summary> /// <param name="moveToStar">The star that the deep space location is near to</param> /// <returns>A <see cref="DeepSpace"/> instance</returns> public AstronomicalObject GetDeepSpaceObject(AstronomicalObject moveToStar) { AstronomicalObject result = FindObjectByName(DEEP_SPACE_NAME, StringComparison.InvariantCulture); if (result == null) { result = new AstronomicalObject(DEEP_SPACE_NAME, this, AstronomicalObjectType.DeepSpace, moveToStar); } else { result.Star = moveToStar; } return(result); }
/// <summary> /// Adds a new entry into the list of stars we know the distance from /// </summary> /// <param name="otherObject">Another <see cref="Star"/> instance.</param> /// <param name="distance">The distance between the current star and the /// star specified in the <paramref name="otherObject"/> parameter.</param> /// <exception cref="ArgumentNullException">The <paramref name="otherObject"/> parameter is null.</exception> /// <exception cref="ArgumentException">The <paramref name="otherObject"/> is equal to the current star</exception> /// <exception cref="ArgumentOutOfRangeException">The <paramref name="distance"/> parameter is negative /// or equals zero.</exception> /// <remarks> /// This method can be called either to add a new distance, or to modify an existing distance. /// The data will be added in the <see cref="KnownObjectProximities"/> property of both the current star /// and the star provided in the <paramref name="otherObject"/> parameter. /// </remarks> /// <seealso cref="KnownObjectProximities"/> public void RegisterDistanceFrom(AstronomicalObject otherObject, float distance) { if (otherObject == null) { throw new ArgumentNullException(); } if (otherObject == this) { throw new ArgumentException("I cannot set a distance between me and myself !", "otherStar"); } if (distance <= 0) { throw new ArgumentOutOfRangeException("Invalid distance", "distance"); } KnownObjectProximities.Set(otherObject, distance); otherObject.KnownObjectProximities.Set(this, distance); }
/// <summary> /// Creates a new <see cref="AstronomicalObject"/> orbiting around this star. /// </summary> /// <param name="name">A name for the new object</param> /// <param name="star">The <see cref="Star"/> system that will contain the new object</param> /// <returns>The newly created <see cref="AstronomicalObject"/></returns> public static AstronomicalObject CreateAstronomicalObject(string name, AstronomicalObject star) { if (name == null) { throw new ArgumentNullException("name", "A star name cannot be null"); } AstronomicalObject result = star.Environment.FindObjectByName(name); if (result == null) { result = new AstronomicalObject(name, star.Environment, AstronomicalObjectType.NaturalObject, star); } else { result.Type = AstronomicalObjectType.NaturalObject; result.Star = star; } return(result); }
internal static bool Load(XmlReader reader, EliteEnvironment container) { if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "trade") { return(false); } Commodity commodity = null; AstronomicalObject station = null; float sellingPrice = 0; float buyingPrice = 0; int stock = 0; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "commodity": commodity = container.FindCommodityByName(reader.Value); if (commodity == null) { throw new EnvironmentLoadException(String.Format("Unknown commodity name '{0}'", reader.Value), reader); } break; case "station": station = container.Stations.Where(s => s.Name == reader.Value).FirstOrDefault(); if (station == null) { throw new EnvironmentLoadException(String.Format("Unknown station name '{0}'", reader.Value), reader); } break; case "sellingPrice": sellingPrice = reader.ReadFloat(); break; case "buyingPrice": buyingPrice = reader.ReadFloat(); break; case "stock": stock = reader.ReadInt(); break; } } if (commodity == null) { throw new EnvironmentLoadException("Missing commodity for a trade entry", reader); } if (station == null) { throw new EnvironmentLoadException("Missing station for a trade entry", reader); } station.CreateTrade(commodity, sellingPrice, buyingPrice, stock); reader.Read(); return(true); }
internal Trade(AstronomicalObject station, Commodity commodity) { Station = station; Commodity = commodity; DataDate = DateTime.Now; }
/// <summary> /// Loads an environment from the specified stream. /// </summary> /// <param name="source">A stream containing data previously written by the <see cref="Save"/> method.</param> /// <exception cref="ArgumentNullException">The provided stream is null</exception> /// <exception cref="ArgumentException">The provided stream cannot be read</exception> /// <exception cref="EnvironmentLoadException">The stream contained invalid data</exception> public void Load(Stream source) { if (source == null) { throw new ArgumentNullException("source"); } if (!source.CanRead) { throw new ArgumentException("Source stream must be readable", "source"); } XmlReaderSettings xmlSettings = new XmlReaderSettings() { CloseInput = false, }; using (XmlReader reader = XmlReader.Create(source, xmlSettings)) { string currentName = null; while (reader.Read()) { // Move to the root element if (reader.IsStartElement()) { break; } } while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { //case "autodistance": // AutoDistanceEnabled = reader.ReadBool(); // break; case "current": currentName = reader.Value; break; } } while (reader.Read()) { if (reader.IsStartElement()) { switch (reader.LocalName) { case "commodities": // Using a subtree reader ensures that the rest of the loading // code will not get past the end of the container, and // that we are positionned at the end of the container after // the reading is done using (XmlReader commoditiesReader = reader.ReadSubtree()) { while (commoditiesReader.Read()) { if (commoditiesReader.IsStartElement()) { Commodity.Load(commoditiesReader, this); } } } break; case "objects": using (XmlReader objectsReader = reader.ReadSubtree()) { objectsReader.Read(); while (objectsReader.Read()) { if (objectsReader.IsStartElement()) { if (!AstronomicalObject.Load(reader, this)) { break; } } } } break; case "trades": using (XmlReader tradesReader = reader.ReadSubtree()) { while (tradesReader.Read()) { if (tradesReader.IsStartElement()) { Trade.Load(tradesReader, this); } } } break; } } } if (currentName != null) { CurrentSituation.CurrentLocation = FindObjectByName(currentName); } } }
internal static bool Load(XmlReader reader, EliteEnvironment container) { if (!reader.IsStartElement()) { return(false); } AstronomicalObjectType type = AstronomicalObjectType.Unspecified; if (Enum.TryParse <AstronomicalObjectType>(reader.LocalName, true, out type)) { string name = null; AstronomicalObject star = null; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "name": name = reader.Value; break; case "star": star = container.FindObjectByName(reader.Value, AstronomicalObjectType.Star); if (star == null) { throw new EnvironmentLoadException(String.Format("The star {0} could not be found", reader.Value), reader); } break; } } if (name == null) { throw new EnvironmentLoadException("Missing name for astronomical object entry", reader); } AstronomicalObject result = new AstronomicalObject(name, container, type, star); // Read child elements int curDepth = reader.Depth; while (reader.Read() && reader.Depth >= curDepth) { if (reader.NodeType == XmlNodeType.Element) { switch (reader.LocalName) { case "notes": result.UserNotes = reader.ReadElementContentAsString(); break; } } } return(true); } else { return(false); } }
// UNKNOWN // Star // Planet / Moon / Belt // Unidentified signals // Station internal AstronomicalObject(string name, EliteEnvironment environment, AstronomicalObjectType type, AstronomicalObject star) { Name = name; Environment = environment; ObjectsInternal = new ObservableCollection <AstronomicalObject>(); Objects = new ReadOnlyObservableCollection <AstronomicalObject>(ObjectsInternal); KnownObjectProximities = new StarProximityCollection(); _trades = new ObservableCollection <Trade>(); Trades = new ReadOnlyObservableCollection <Trade>(_trades); _commodityIndex = new Dictionary <Commodity, int>(); if (environment.AutoDistanceEnabled) { float distance = 0; foreach (AstronomicalObject otherObject in environment.Objects) { if (DistancesDB.TryGetDistance(this, otherObject, out distance)) { RegisterDistanceFrom(otherObject, distance); } } } Type = type; Star = star ?? this; Environment.ObjectsInternal.Add(this); }