public ActionResult SellGoods(int goodId, int quantity, int price) { ShipGood shipGood = this.ControllerGame.CurrentPlayer.Ship.GetGood(goodId); if (shipGood != null) { try { shipGood.Sell(this.ControllerGame.CurrentPlayer.Ship, quantity, price); return(RedirectToAction("ListGoods")); } catch (ArgumentOutOfRangeException ex) { // Log this exception ExceptionPolicy.HandleException(ex, "Controller Policy"); if (ex.ParamName == "price") { // Go to the SellGoodsPriceChange view // Price has changed on the good // Confirm the player still wants to sell the good ViewData["goodId"] = goodId; ViewData["quantity"] = quantity; ViewData["oldPrice"] = price; ViewData["goodName"] = shipGood.Good.Name; // Try to get the current price SystemGood systemGood = this.ControllerGame.CurrentPlayer.Ship.CosmoSystem.GetGood(goodId); if (systemGood != null) { ViewData["newPrice"] = systemGood.Price; } return(View("SellGoodsPriceChange")); } else { ModelState.AddModelError("quantity", ex.Message, quantity); } } catch (InvalidOperationException ex) { // Log this exception ExceptionPolicy.HandleException(ex, "Controller Policy"); ModelState.AddModelError("goodId", ex.Message, quantity); } } else { ModelState.AddModelError("goodId", "Good is not bought in the system", goodId); } return(View()); }
public void SellNotSold() { CosmoMongerDbDataContext db = CosmoManager.GetDbContext(); // Setup player Player testPlayer = this.CreateTestPlayer(); Ship testShip = testPlayer.Ship; CosmoSystem startingSystem = testShip.CosmoSystem; GameManager manager = new GameManager(testPlayer.User.UserName); // Store the player starting cash int playerStartingCash = testPlayer.Ship.Credits; // Add some water to this ship for us to sell Good water = (from g in db.Goods where g.Name == "Water" select g).SingleOrDefault(); Assert.That(water, Is.Not.Null, "We should have a Water good"); ShipGood shipGood = new ShipGood(); shipGood.Good = water; shipGood.Quantity = 10; shipGood.Ship = testShip; testShip.ShipGoods.Add(shipGood); // Verify that the good is for sell in the current system SystemGood systemWater = startingSystem.GetGood(water.GoodId); if (systemWater != null) { // Remove the good from the system db.SystemGoods.DeleteOnSubmit(systemWater); db.SubmitChanges(); } try { shipGood.Sell(testShip, 10, systemWater.Price); } catch (InvalidOperationException ex) { // Correct Assert.That(ex, Is.Not.Null, "InvalidOperationException should be valid"); return; } Assert.Fail("Player should not been able to sell in the system when the good was not sold in the system"); }
public void BuyNotEnoughCash() { CosmoMongerDbDataContext db = CosmoManager.GetDbContext(); // Setup player Player testPlayer = this.CreateTestPlayer(); Ship testShip = testPlayer.Ship; CosmoSystem startingSystem = testShip.CosmoSystem; GameManager manager = new GameManager(testPlayer.User.UserName); // Reduce the player starting cash testPlayer.Ship.Credits = 10; // Check that the ship is empty Assert.That(testShip.ShipGoods.Count, Is.EqualTo(0), "Ship should start out with no goods on-board"); // Add some water to the starting system for this ship to buy Good water = (from g in db.Goods where g.Name == "Water" select g).SingleOrDefault(); Assert.That(water, Is.Not.Null, "We should have a Water good"); startingSystem.AddGood(water.GoodId, 20); // Verify that the good was added to the system SystemGood systemWater = startingSystem.GetGood(water.GoodId); Assert.That(systemWater, Is.Not.Null, "System should now have a water SystemGood"); Assert.That(systemWater.Quantity, Is.GreaterThanOrEqualTo(20), "System should now have at least 20 water goods"); int playerCost = (int)(systemWater.PriceMultiplier * water.BasePrice) * systemWater.Quantity; int systemStartingCount = systemWater.Quantity; try { systemWater.Buy(testShip, 20, systemWater.Price); } catch (ArgumentException ex) { Assert.That(ex.ParamName, Is.EqualTo("quantity"), "Quantity to buy should be the invalid argument"); return; } Assert.Fail("Player should not been able to buy more goods than they can afford"); }
public void SellNotEnoughGoods() { CosmoMongerDbDataContext db = CosmoManager.GetDbContext(); // Setup player Player testPlayer = this.CreateTestPlayer(); Ship testShip = testPlayer.Ship; CosmoSystem startingSystem = testShip.CosmoSystem; GameManager manager = new GameManager(testPlayer.User.UserName); // Add some water to this ship for us to sell Good water = (from g in db.Goods where g.Name == "Water" select g).SingleOrDefault(); Assert.That(water, Is.Not.Null, "We should have a Water good"); ShipGood shipGood = new ShipGood(); shipGood.Good = water; shipGood.Quantity = 10; shipGood.Ship = testShip; testShip.ShipGoods.Add(shipGood); db.SubmitChanges(); // Verify that the good is for sell in the current system SystemGood systemWater = startingSystem.GetGood(water.GoodId); if (systemWater == null) { startingSystem.AddGood(water.GoodId, 0); systemWater = startingSystem.GetGood(water.GoodId); } try { shipGood.Sell(testShip, 20, systemWater.Price); } catch (ArgumentOutOfRangeException ex) { Assert.That(ex.ParamName, Is.EqualTo("quantity"), "Quantity to sell should be the invalid argument"); return; } Assert.Fail("Player should not been able to sell more goods than aboard"); }
public void Sell() { CosmoMongerDbDataContext db = CosmoManager.GetDbContext(); // Setup player Player testPlayer = this.CreateTestPlayer(); Ship testShip = testPlayer.Ship; CosmoSystem startingSystem = testShip.CosmoSystem; GameManager manager = new GameManager(testPlayer.User.UserName); // Store the player starting cash int playerStartingCash = testPlayer.Ship.Credits; // Add some water to this ship for us to sell Good water = (from g in db.Goods where g.Name == "Water" select g).SingleOrDefault(); Assert.That(water, Is.Not.Null, "We should have a Water good"); ShipGood shipGood = new ShipGood(); shipGood.Good = water; shipGood.Quantity = 10; shipGood.Ship = testShip; testShip.ShipGoods.Add(shipGood); // Verify that the good is for sell in the current system SystemGood systemWater = startingSystem.GetGood(water.GoodId); if (systemWater == null) { startingSystem.AddGood(water.GoodId, 0); systemWater = startingSystem.GetGood(water.GoodId); } int playerProfit = systemWater.Price * 10; int systemStartingCount = systemWater.Quantity; shipGood.Sell(testShip, 10, systemWater.Price); Assert.That(systemWater.Quantity, Is.EqualTo(systemStartingCount + 10), "System should now have 10 more water goods"); Assert.That(testPlayer.Ship.Credits, Is.EqualTo(playerStartingCash + playerProfit), "Player should have more cash credits now after selling"); }
public void AddGood() { CosmoMongerDbDataContext db = CosmoManager.GetDbContext(); CosmoSystem firstSystem = (from s in db.CosmoSystems select s).FirstOrDefault(); Assert.That(firstSystem, Is.Not.Null, "We need at least one system in the galaxy"); // Add some water to the the system Good water = (from g in db.Goods where g.Name == "Water" select g).SingleOrDefault(); Assert.That(water, Is.Not.Null, "We should have a Water good"); firstSystem.AddGood(water.GoodId, 100); // Verify that the good was added to the system SystemGood systemWater = firstSystem.GetGood(water.GoodId); Assert.That(systemWater, Is.Not.Null, "System should now have a water SystemGood"); Assert.That(systemWater.Quantity, Is.GreaterThanOrEqualTo(100), "System should now have at least 100 water goods"); }
public void BuyNotEnoughGoods() { CosmoMongerDbDataContext db = CosmoManager.GetDbContext(); // Setup player Player testPlayer = this.CreateTestPlayer(); Ship testShip = testPlayer.Ship; CosmoSystem startingSystem = testShip.CosmoSystem; GameManager manager = new GameManager(testPlayer.User.UserName); // Check that the ship is empty Assert.That(testShip.ShipGoods.Count, Is.EqualTo(0), "Ship should start out with no goods on-board"); // Add some water to the starting system for this ship to buy Good water = (from g in db.Goods where g.Name == "Water" select g).SingleOrDefault(); Assert.That(water, Is.Not.Null, "We should have a Water good"); startingSystem.AddGood(water.GoodId, 5); // Verify that the good was added to the system SystemGood systemWater = startingSystem.GetGood(water.GoodId); // Make sure only 5 are at the system systemWater.Quantity = 5; try { systemWater.Buy(testShip, 20, systemWater.Price); } catch (ArgumentOutOfRangeException ex) { Assert.That(ex.ParamName, Is.EqualTo("quantity"), "Quantity to buy should be the invalid argument"); return; } Assert.Fail("Player should not been able to buy more goods than at the system"); }
public void Buy() { CosmoMongerDbDataContext db = CosmoManager.GetDbContext(); // Setup player Player testPlayer = this.CreateTestPlayer(); Ship testShip = testPlayer.Ship; CosmoSystem startingSystem = testShip.CosmoSystem; GameManager manager = new GameManager(testPlayer.User.UserName); // Store the player starting cash int playerStartingCash = testPlayer.Ship.Credits; // Check that the ship is empty Assert.That(testShip.ShipGoods.Count, Is.EqualTo(0), "Ship should start out with no goods on-board"); // Add some water to the starting system for this ship to buy Good water = (from g in db.Goods where g.Name == "Water" select g).SingleOrDefault(); Assert.That(water, Is.Not.Null, "We should have a Water good"); startingSystem.AddGood(water.GoodId, 20); // Verify that the good was added to the system SystemGood systemWater = startingSystem.GetGood(water.GoodId); Assert.That(systemWater, Is.Not.Null, "System should now have a water SystemGood"); Assert.That(systemWater.Quantity, Is.GreaterThanOrEqualTo(20), "System should now have at least 20 water goods"); int playerCost = systemWater.Price * 20; int systemStartingCount = systemWater.Quantity; systemWater.Buy(testShip, 20, systemWater.Price); Assert.That(systemWater.Quantity, Is.EqualTo(systemStartingCount - 20), "System should now have 20 few water goods"); Assert.That(testPlayer.Ship.Credits, Is.EqualTo(playerStartingCash - playerCost), "Player should have less cash credits now after buying"); }
/// <summary> /// Updates the system good count, causing systems to produce goods as needed. /// </summary> private void UpdateSystemGoodCount() { CosmoMongerDbDataContext db = CosmoManager.GetDbContext(); Dictionary <string, object> props; foreach (Good good in db.Goods) { // Get the total number of this good type available in all systems int totalSystemGoodCount = good.SystemGoods.Sum(x => x.Quantity); double targetBreak = (((double)good.TargetCount) / 10.0); // Check if we need to add some of this good to the galaxy while (totalSystemGoodCount < good.TargetCount) { // Randomly select a system with equal to or fewer than targetBreak number of goods to produce. var goodProducingSystems = (from g in good.SystemGoods where g.ProductionFactor > 0 && g.Quantity <= targetBreak select g); if (goodProducingSystems.Count() == 0) { // No systems produce this good? // Continue on to the next good type break; } SystemGood selectedProducingSystemGood = goodProducingSystems.ElementAt(rnd.Next(goodProducingSystems.Count())); // Produce the good, using the count needed and the production factor double adjustedProductionFactor = (rnd.NextDouble() + selectedProducingSystemGood.ProductionFactor) / 2; int lackingGoodCount = (int)(rnd.Next(10) * adjustedProductionFactor); selectedProducingSystemGood.Quantity += lackingGoodCount; props = new Dictionary <string, object> { { "SystemId", selectedProducingSystemGood.SystemId }, { "GoodId", selectedProducingSystemGood.GoodId }, { "Quantity", selectedProducingSystemGood.Quantity }, { "AddedQuantity", lackingGoodCount } }; Logger.Write("Producing Goods", "NPC", 400, 0, TraceEventType.Verbose, "Producing Goods", props); // Update the total good count totalSystemGoodCount += lackingGoodCount; try { // Send changes to database db.SubmitChanges(ConflictMode.ContinueOnConflict); } catch (ChangeConflictException ex) { ExceptionPolicy.HandleException(ex, "SQL Policy"); // Another thread has made changes to this SystemGood row, // which could be from someone buying or selling the good at a system // Best case to resolve this would be to simply start over in the good production, // because the good quantity has been changed by another method. foreach (ObjectChangeConflict occ in db.ChangeConflicts) { // Refresh values from database occ.Resolve(RefreshMode.OverwriteCurrentValues); } continue; } } // Now consume some of this good in the galaxy // Randomly select a good at a system to consume where the quantity is equal to or higher // than targetBreak number of goods var goodConsumingSystems = (from g in good.SystemGoods where g.ConsumptionFactor > 0 && g.Quantity >= targetBreak && g.Quantity > 0 select g); if (goodConsumingSystems.Count() == 0) { // No systems consume this good? // Continue on to the next good type continue; } SystemGood selectedConsumingSystemGood = goodConsumingSystems.ElementAt(rnd.Next(goodConsumingSystems.Count())); // Consuming the good, using the count needed and the consumption factor double adjustedConsumptionFactor = (rnd.NextDouble() + selectedConsumingSystemGood.ConsumptionFactor) / 2; int usageGoodCount = (int)(rnd.Next(10) * adjustedConsumptionFactor); usageGoodCount = Math.Min(usageGoodCount, selectedConsumingSystemGood.Quantity); selectedConsumingSystemGood.Quantity -= usageGoodCount; props = new Dictionary <string, object> { { "SystemId", selectedConsumingSystemGood.SystemId }, { "GoodId", selectedConsumingSystemGood.GoodId }, { "Quantity", selectedConsumingSystemGood.Quantity }, { "RemovedQuantity", usageGoodCount } }; Logger.Write("Consuming Goods", "NPC", 400, 0, TraceEventType.Verbose, "Consuming Goods", props); try { // Send changes to database db.SubmitChanges(ConflictMode.ContinueOnConflict); } catch (ChangeConflictException ex) { ExceptionPolicy.HandleException(ex, "SQL Policy"); // Another thread has made changes to this SystemGood row, // which could be from someone buying or selling the good at a system // Best case to resolve this would be to simply ignore the good consumption, // we like to produce more than we consume foreach (ObjectChangeConflict occ in db.ChangeConflicts) { // Refresh values from database occ.Resolve(RefreshMode.OverwriteCurrentValues); } } } }
/// <summary> /// Does the action. /// </summary> public override void DoAction() { if (!this.SetNextActionDelay(NpcTrader.DelayBeforeNextAction)) { return; } CosmoMongerDbDataContext db = CosmoManager.GetDbContext(); Ship npcShip = this.npcRow.Ship; // Check if we are still traveling npcShip.CheckIfTraveling(); // Check if we are currently in combat if (npcShip.InProgressCombat != null) { // In Combat! this.DoCombat(); } else if (this.npcRow.NextTravelTime < DateTime.UtcNow) { // Create an array of goods that the Trader has onboard ShipGood[] goods = npcShip.GetGoods().Where(g => g.Quantity > 0).ToArray(); // goodCount != 0, sell all the trader's goods foreach (ShipGood good in goods) { // Get the number of this good type onboard the Trader's ship int shipGoodQuantity = good.Quantity; // Find the price of the good int shipGoodPrice = 0; try { good.Sell(npcShip, shipGoodQuantity, shipGoodPrice); } catch (InvalidOperationException ex) { // Log this exception ExceptionPolicy.HandleException(ex, "NPC Policy"); } } // This is the minimum amount of money a trader should have before buying goods int baseCreditsSizeAdjusted = BaseCreditMultiplier * npcShip.CargoSpaceTotal; // Check if we need to give this trader some credits if (npcShip.Credits < baseCreditsSizeAdjusted) { // Poor trader has no credits, give him some to start npcShip.Credits = baseCreditsSizeAdjusted; } // Trader buys first good SystemGood good1 = (from g in npcShip.CosmoSystem.SystemGoods orderby(g.PriceMultiplier) ascending select g).FirstOrDefault(); // This is the maximum number a Trader can purchase double numberCanBuy = Math.Floor((double)npcShip.Credits / good1.Price); // This is the maximum number we want the Trader to purchase double numberToBuy = Math.Ceiling((double)npcShip.CargoSpaceFree / 2); // Make sure that the Trader buys as many of good1 as credits allow int numberBuying = (int)Math.Min(numberCanBuy, numberToBuy); // Insures that Traders attempt to buy the proper number of good1 int properNumber = (int)Math.Min(numberBuying, good1.Quantity); try { good1.Buy(npcShip, properNumber, good1.Price); } catch (InvalidOperationException ex) { // Log this exception ExceptionPolicy.HandleException(ex, "NPC Policy"); } // Find all the systems within range CosmoSystem[] inRangeSystems = npcShip.GetInRangeSystems(); // Finds the system with the highest PriceMultiplier CosmoSystem targetSystem = (from g in db.SystemGoods where inRangeSystems.Contains(g.CosmoSystem) && g.Good == good1.Good orderby(g.PriceMultiplier) descending select g.CosmoSystem).FirstOrDefault(); // Get references to the Good entities for all the SystemGoods sold in the target system IEnumerable <Good> goodsInTargetSystem = targetSystem.SystemGoods.Select(g => g.Good); // Get references to the Good entites for the all the SystemGoods sold in the current system IEnumerable <Good> goodsInCurrentSystem = npcShip.CosmoSystem.SystemGoods.Select(g => g.Good); // Do an intersetion of both, getting a list of goods sold in both systems IEnumerable <Good> goodsInBoth = goodsInTargetSystem.Intersect(goodsInCurrentSystem); // Look in the current system for goods sold in both, sorting by PriceMultiplier (lowest at top) // and taking the top good in the results SystemGood good2 = (from g in npcShip.CosmoSystem.SystemGoods where goodsInBoth.Contains(g.Good) && g != good1 orderby g.PriceMultiplier ascending select g).FirstOrDefault(); // This is the maximum number a Trader can purchase numberCanBuy = Math.Floor((double)npcShip.Credits / good2.Price); // This is the maximum number we want the Trader to purchase numberToBuy = Math.Ceiling((double)npcShip.CargoSpaceFree); // Make sure that the Trader buys as many of good1 as credits allow numberBuying = (int)Math.Min(numberCanBuy, numberToBuy); // Insures that Traders attempt to buy the proper number of good1 properNumber = (int)Math.Min(numberBuying, good2.Quantity); try { good2.Buy(npcShip, properNumber, good2.Price); } catch (InvalidOperationException ex) { // Log this exception ExceptionPolicy.HandleException(ex, "NPC Policy"); } this.DoTravel(targetSystem); // Set next travel time this.npcRow.NextTravelTime = DateTime.UtcNow.AddSeconds(this.rnd.Next(60, 120)); } else { Dictionary <string, object> props = new Dictionary <string, object> { { "NpcId", this.npcRow.NpcId }, { "NextTravelTime", this.npcRow.NextTravelTime }, { "UtcNow", DateTime.UtcNow } }; Logger.Write("Waiting for NextTravelTime", "NPC", 200, 0, TraceEventType.Verbose, "Trader Wait", props); } db.SaveChanges(); }