diff --git a/.idea/.idea.Lemonade/.idea/.gitignore b/.idea/.idea.Lemonade/.idea/.gitignore new file mode 100644 index 0000000..319f19f --- /dev/null +++ b/.idea/.idea.Lemonade/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/modules.xml +/projectSettingsUpdater.xml +/.idea.Lemonade.iml +/contentModel.xml diff --git a/Lemonade/AnimationScreen.cs b/Lemonade/AnimationScreen.cs index 5f90472..5d5b090 100644 --- a/Lemonade/AnimationScreen.cs +++ b/Lemonade/AnimationScreen.cs @@ -9,20 +9,23 @@ namespace Lemonade { public class AnimationScreen : CenteredScreen { - public event OkDelegate Ok; public delegate void OkDelegate(); - private Image imgControl; + + private readonly Image imgControl; + public AnimationScreen(Settings set) : base(100, 20, Black, set.Color) { ContentPanel.ForeColor = DarkGray; Title = "Lemonade - Anim"; - imgControl = new Image(new Pixel[0,0]); + imgControl = new Image(new Pixel[0, 0]); SetWeather(new Weather()); ContentPanel.Controls.Add(imgControl); Input += (screen, args) => Ok?.Invoke(); Close += (screen, args) => Ok?.Invoke(); } + public event OkDelegate Ok; + public void SetWeather(Weather w) { Title = $"Lemonade - Weather: {w}"; diff --git a/Lemonade/Fakku.cs b/Lemonade/Fakku.cs index 4316803..ad8101b 100644 --- a/Lemonade/Fakku.cs +++ b/Lemonade/Fakku.cs @@ -4,14 +4,11 @@ using CC_Functions.Commandline.TUI; namespace Lemonade { + //Mostly kang from Stackoverflow public static class EllipseDrawer { private static PointF GetEllipsePointFromX(float x, float a, float b) => - //(x/a)^2 + (y/b)^2 = 1 - //(y/b)^2 = 1 - (x/a)^2 - //y/b = -sqrt(1 - (x/a)^2) --Neg root for upper portion of the plane - //y = b*-sqrt(1 - (x/a)^2) - new PointF(x, b * -(float)Math.Sqrt(1 - x * x / a / a)); + new PointF(x, b * -(float) Math.Sqrt(1 - x * x / a / a)); public static void DrawEllipse(this Pixel[,] target, Rectangle area, Pixel basePixel) { @@ -27,52 +24,47 @@ namespace Lemonade private static void DrawEllipse(bool[,] pixels, Rectangle area) { - // Get the size of the matrix int matrixWidth = pixels.GetLength(0); int matrixHeight = pixels.GetLength(1); int offsetY = area.Top; int offsetX = area.Left; - // Figure out how big the ellipse is float ellipseWidth = area.Width; float ellipseHeight = area.Height; - // Figure out the radiuses of the ellipses float radiusX = ellipseWidth / 2; float radiusY = ellipseHeight / 2; - //Keep track of the previous y position int prevY = 0; bool firstRun = true; - // Loop through the points in the matrix for (int x = 0; x <= radiusX; ++x) { int xPos = x + offsetX; - int rxPos = (int)ellipseWidth - x - 1 + offsetX; + int rxPos = (int) ellipseWidth - x - 1 + offsetX; if (xPos < 0 || rxPos < xPos || xPos >= matrixWidth) continue; - PointF pointOnEllipseBoundCorrespondingToXMatrixPosition = GetEllipsePointFromX(x - radiusX, radiusX, radiusY); - int y = (int) Math.Floor(pointOnEllipseBoundCorrespondingToXMatrixPosition.Y + (int)radiusY); + PointF pointOnEllipseBoundCorrespondingToXMatrixPosition = + GetEllipsePointFromX(x - radiusX, radiusX, radiusY); + int y = (int) Math.Floor(pointOnEllipseBoundCorrespondingToXMatrixPosition.Y + (int) radiusY); int yPos = y + offsetY; - int ryPos = (int)ellipseHeight - y - 1 + offsetY; + int ryPos = (int) ellipseHeight - y - 1 + offsetY; if (yPos >= 0) { if (xPos < matrixWidth && yPos < matrixHeight) pixels[xPos, yPos] = true; - if(xPos < matrixWidth && ryPos > -1 && ryPos < matrixHeight) pixels[xPos, ryPos] = true; + if (xPos < matrixWidth && ryPos > -1 && ryPos < matrixHeight) pixels[xPos, ryPos] = true; if (rxPos < matrixWidth) { if (yPos < matrixHeight) pixels[rxPos, yPos] = true; if (ryPos > -1 && ryPos < matrixHeight) pixels[rxPos, ryPos] = true; } } - //While there's a >1 jump in y, fill in the gap (assumes that this is not the first time we've tracked y, x != 0) for (int j = prevY - 1; !firstRun && j > y - 1 && y > 0; --j) { int jPos = j + offsetY; - int rjPos = (int)ellipseHeight - j - 1 + offsetY; - if(jPos == rjPos - 1) continue; - if(jPos > -1 && jPos < matrixHeight) pixels[xPos, jPos] = true; - if(rjPos > -1 && rjPos < matrixHeight) pixels[xPos, rjPos] = true; + int rjPos = (int) ellipseHeight - j - 1 + offsetY; + if (jPos == rjPos - 1) continue; + if (jPos > -1 && jPos < matrixHeight) pixels[xPos, jPos] = true; + if (rjPos > -1 && rjPos < matrixHeight) pixels[xPos, rjPos] = true; if (rxPos < matrixWidth) { - if(jPos > -1 && jPos < matrixHeight) pixels[rxPos, jPos] = true; - if(rjPos > -1 && rjPos < matrixHeight) pixels[rxPos, rjPos] = true; + if (jPos > -1 && jPos < matrixHeight) pixels[rxPos, jPos] = true; + if (rjPos > -1 && rjPos < matrixHeight) pixels[rxPos, rjPos] = true; } } firstRun = false; @@ -82,14 +74,12 @@ namespace Lemonade { ++yPos; --ryPos; - // Set all four points in the matrix we just learned about - // also, make the indication that for the rest of this row, we need to fill the body of the ellipse - if(yPos > -1 && yPos < matrixHeight) pixels[xPos, yPos] = true; - if(ryPos > -1 && ryPos < matrixHeight) pixels[xPos, ryPos] = true; + if (yPos > -1 && yPos < matrixHeight) pixels[xPos, yPos] = true; + if (ryPos > -1 && ryPos < matrixHeight) pixels[xPos, ryPos] = true; if (rxPos < matrixWidth) { - if(yPos > -1 && yPos < matrixHeight) pixels[rxPos, yPos] = true; - if(ryPos > -1 && ryPos < matrixHeight) pixels[rxPos, ryPos] = true; + if (yPos > -1 && yPos < matrixHeight) pixels[rxPos, yPos] = true; + if (ryPos > -1 && ryPos < matrixHeight) pixels[rxPos, ryPos] = true; } } } diff --git a/Lemonade/Image.cs b/Lemonade/Image.cs index bd09869..e6fd5d7 100644 --- a/Lemonade/Image.cs +++ b/Lemonade/Image.cs @@ -7,8 +7,8 @@ namespace Lemonade public Pixel[,] Img; public Image(Pixel[,] img) => Img = img; - public override Pixel[,] Render() => Img; - public override bool Selectable { get; } = false; + + public override Pixel[,] Render() => Img; } } \ No newline at end of file diff --git a/Lemonade/PlayerState.cs b/Lemonade/PlayerState.cs index 986988b..39a1d15 100644 --- a/Lemonade/PlayerState.cs +++ b/Lemonade/PlayerState.cs @@ -5,13 +5,13 @@ namespace Lemonade public class PlayerState { public int Budget; - public int Glasses; - public int Signs; - public int GlassPrice; - public int Expenses; public int Earnings; - public int Sales; + public int Expenses; + public int Glasses; + public int GlassPrice; public int Number; + public int Sales; + public int Signs; public PlayerState(int number) { @@ -22,13 +22,21 @@ namespace Lemonade public void CalculateIncome(int signCost, int glassCost, Weather weather, Settings settings) { Expenses = signCost * Signs + glassCost * Glasses; - - double weatherFactor = (weather.Factor * 2 + 1d) / (settings.DifficultyFactor * 2d + 1d) / 2d; //calculate a scalar for sales between 0.2 and 1.5 based on the weather factor - double signFactor = 2.5d - ((settings.DifficultyFactor + 0.1) * 2d) / (Signs + 1d); //calculate a scalar between 0.3 and (basically) 2.5 based on the amount of signs - double priceFactor = 3 / (GlassPrice / 2 + 1); //calculate a scalar between (basically) 0 and 3 based on the price of lemonades - Sales = (int)Math.Max(Math.Min(weatherFactor * signFactor * priceFactor * Glasses, Glasses), 0); //Multiply the factors and sanitize results - Earnings = (int)Math.Floor((double)Sales * GlassPrice); //Convert result to integer - + + double weatherFactor = + (weather.Factor * 2 + 1d) / (settings.DifficultyFactor * 2d + 1d) / + 2d; //calculate a scalar for sales between 0.2 and 1.5 based on the weather factor + double signFactor = + 2.5d - (settings.DifficultyFactor + 0.1) * 2d / + (Signs + 1d); //calculate a scalar between 0.3 and (basically) 2.5 based on the amount of signs + double + priceFactor = + 3 / (GlassPrice / 2 + + 1); //calculate a scalar between (basically) 0 and 3 based on the price of lemonades + Sales = (int) Math.Max(Math.Min(weatherFactor * signFactor * priceFactor * Glasses, Glasses), + 0); //Multiply the factors and sanitize results + Earnings = (int) Math.Floor((double) Sales * GlassPrice); //Convert result to integer + Budget += Earnings - Expenses; } } diff --git a/Lemonade/Program.cs b/Lemonade/Program.cs index 1a7ba7f..de43579 100644 --- a/Lemonade/Program.cs +++ b/Lemonade/Program.cs @@ -2,9 +2,9 @@ namespace Lemonade { - class Program + internal class Program { - static void Main(string[] args) + private static void Main(string[] args) { Console.BackgroundColor = ConsoleColor.Black; Console.ForegroundColor = ConsoleColor.White; diff --git a/Lemonade/ResultScreen.cs b/Lemonade/ResultScreen.cs index 8c2d778..1e6bd7d 100644 --- a/Lemonade/ResultScreen.cs +++ b/Lemonade/ResultScreen.cs @@ -1,7 +1,5 @@ using System; -using System.Collections; using System.Collections.Generic; -using System.Diagnostics; using System.Drawing; using CC_Functions.Commandline; using CC_Functions.Commandline.TUI; @@ -10,9 +8,10 @@ namespace Lemonade { public class ResultScreen : CenteredScreen { - public event OkDelegate Ok; public delegate void OkDelegate(); - private Label lab; + + private readonly Label lab; + public ResultScreen(Settings settings) : base(200, 20, ConsoleColor.Black, settings.Color) { ContentPanel.ForeColor = ConsoleColor.DarkGray; @@ -23,18 +22,25 @@ namespace Lemonade Close += (screen, args) => Ok?.Invoke(); } + public event OkDelegate Ok; + public void Setup(IEnumerable players) { - lab.Content = players.ToStringTable(new[] {"Player", "Glasses made", "Earnings per glass", "Glasses sold", "Signs made", "Income", "Expenses", "Profit", "Budget"}, - (s) => s.Number, - (s) => s.Glasses, - (s) => s.GlassPrice, - (s) => s.Sales, - (s) => s.Signs, - (s) => s.Earnings, - (s) => s.Expenses, - (s) => s.Earnings - s.Expenses, - (s) => s.Budget); + lab.Content = players.ToStringTable( + new[] + { + "Player", "Glasses made", "Earnings per glass", "Glasses sold", "Signs made", "Income", "Expenses", + "Profit", "Budget" + }, + s => s.Number, + s => s.Glasses, + s => s.GlassPrice, + s => s.Sales, + s => s.Signs, + s => s.Earnings, + s => s.Expenses, + s => s.Earnings - s.Expenses, + s => s.Budget); lab.Render(); ActualSize = new Size(lab.Size.Width, lab.Size.Height); } diff --git a/Lemonade/ScreenManager.cs b/Lemonade/ScreenManager.cs index 2972929..31bb689 100644 --- a/Lemonade/ScreenManager.cs +++ b/Lemonade/ScreenManager.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Threading; -using CC_Functions.Commandline.TUI; namespace Lemonade { @@ -12,15 +11,13 @@ namespace Lemonade private readonly ResultScreen _result; private readonly Settings _settings; private readonly TransactionScreen _transaction; - private GameState _state; - private bool _running; - private List _players; private int _currentPlayer; - private bool _initialEvent = true; private int _day; + private bool _initialEvent = true; + private readonly List _players; + private bool _running; + private GameState _state; private Weather _weather; - private int signCost => 15; - private int GlassCost => _day < 5 ? 2 : 4; public ScreenManager(Settings settings) { @@ -31,7 +28,8 @@ namespace Lemonade _state = GameState.Transaction; _currentPlayer = 0; _initialEvent = true; - _transaction.SetUp(_players[_currentPlayer], _settings, _currentPlayer, _day, _weather, signCost, GlassCost); + _transaction.SetUp(_players[_currentPlayer], _settings, _currentPlayer, _day, _weather, signCost, + GlassCost); }; _transaction = new TransactionScreen(settings); _transaction.Ok += (glasses, price, signs) => @@ -49,7 +47,7 @@ namespace Lemonade } else { - _transaction.Tab(true); + _transaction.Tab(); _transaction.Tab(false); } }; @@ -64,12 +62,14 @@ namespace Lemonade for (int i = 0; i < settings.PlayerCount; i++) _players.Add(new PlayerState(i + 1)); } + private int signCost => 15; + private int GlassCost => _day < 5 ? 2 : 4; + public void Run() { _running = true; _state = GameState.Setup; while (_running) - { switch (_state) { case GameState.Setup: @@ -87,7 +87,8 @@ namespace Lemonade case GameState.Transaction: if (_initialEvent) { - _transaction.SetUp(_players[_currentPlayer], _settings, _currentPlayer, _day, _weather, signCost, GlassCost); + _transaction.SetUp(_players[_currentPlayer], _settings, _currentPlayer, _day, _weather, + signCost, GlassCost); _transaction.Render(); _initialEvent = false; } @@ -107,7 +108,6 @@ namespace Lemonade default: throw new ArgumentOutOfRangeException(); } - } } } } \ No newline at end of file diff --git a/Lemonade/Settings.cs b/Lemonade/Settings.cs index 2892f35..f8935d9 100644 --- a/Lemonade/Settings.cs +++ b/Lemonade/Settings.cs @@ -7,14 +7,15 @@ namespace Lemonade { public class Settings { - public bool Color { get; private set; } = true; - public int PlayerCount { get; private set; } - public float DifficultyFactor { get; private set; } public Settings() { Configure(); } + public bool Color { get; private set; } = true; + public int PlayerCount { get; private set; } + public float DifficultyFactor { get; private set; } + public void Configure() { CenteredScreen settingsScreen = new CenteredScreen(200, 20, ConsoleColor.Black, Color) @@ -22,12 +23,12 @@ namespace Lemonade TabPoint = 0, Title = "Lemonade - Settings" #if DEBUG - + "[R to redraw]" + + "[R to redraw]" #endif }; Panel scr = settingsScreen.ContentPanel; scr.ForeColor = ConsoleColor.DarkGray; - + Label playerLabel = new Label("Players"); playerLabel.Point = new Point(scr.Size.Width / 2 - playerLabel.Content.Length / 2, 3); scr.Controls.Add(playerLabel); @@ -35,7 +36,7 @@ namespace Lemonade Slider playerSlider = new Slider {MinValue = 1, Value = 2, Size = new Size(100, 1)}; playerSlider.Point = new Point(scr.Size.Width / 2 - playerSlider.Size.Width / 2, 4); scr.Controls.Add(playerSlider); - + Label difficultyLabel = new Label("Difficulty"); difficultyLabel.Point = new Point(scr.Size.Width / 2 - difficultyLabel.Content.Length / 2, 7); scr.Controls.Add(difficultyLabel); @@ -46,23 +47,23 @@ namespace Lemonade CheckBox colorBox = new CheckBox("Color") {Checked = true}; colorBox.Point = new Point(scr.Size.Width / 2 - (colorBox.Content.Length + 4) / 2, 12); - colorBox.CheckedChanged += (screen, args) => - { - settingsScreen.Color = colorBox.Checked; - }; + colorBox.CheckedChanged += (screen, args) => { settingsScreen.Color = colorBox.Checked; }; #if DEBUG - settingsScreen.Input += (screen, args) => { if (args.Info.Key == ConsoleKey.R) DiffDraw.Draw(Color, true); }; + settingsScreen.Input += (screen, args) => + { + if (args.Info.Key == ConsoleKey.R) DiffDraw.Draw(Color, true); + }; #endif scr.Controls.Add(colorBox); - + Button okButton = new Button("OK"); okButton.Point = new Point(scr.Size.Width / 2 - okButton.Content.Length / 2, 16); scr.Controls.Add(okButton); - + bool visible = true; okButton.Click += (screen, args) => visible = false; settingsScreen.Close += (screen, args) => visible = false; - + settingsScreen.Render(); while (visible) { diff --git a/Lemonade/TransactionScreen.cs b/Lemonade/TransactionScreen.cs index d267473..344e3fe 100644 --- a/Lemonade/TransactionScreen.cs +++ b/Lemonade/TransactionScreen.cs @@ -7,37 +7,38 @@ namespace Lemonade { public class TransactionScreen : CenteredScreen { - public event OkDelegate Ok; public delegate void OkDelegate(int glasses, int price, int signs); - private readonly Label _infoLabel; - private readonly Label _glassesLabel; private readonly Slider _glasses; - private readonly Label _priceLabel; - private readonly Slider _price; - private readonly Label _signsLabel; - private readonly Slider _signs; + private readonly Label _glassesLabel; + + private readonly Label _infoLabel; private readonly Label _infoLabelBottom; + private readonly Slider _price; + private readonly Label _priceLabel; + private readonly Slider _signs; + private readonly Label _signsLabel; + private int _lemonadeCost; private PlayerState _player; private int _signCost; - private int _lemonadeCost; + public TransactionScreen(Settings set) : base(200, 20, ConsoleColor.Black, set.Color) { ContentPanel.ForeColor = ConsoleColor.DarkGray; - + _infoLabel = new Label("[DAY 1]"); _infoLabel.Point = new Point(ContentPanel.Size.Width / 2 - _infoLabel.Content.Length / 2, 0); ContentPanel.Controls.Add(_infoLabel); - + _glassesLabel = new Label("How many glasses of lemonade do you wish to make?"); _glassesLabel.Point = new Point(ContentPanel.Size.Width / 2 - _glassesLabel.Content.Length / 2, 2); ContentPanel.Controls.Add(_glassesLabel); - + _glasses = new Slider {Size = new Size(100, 1)}; _glasses.Point = new Point(ContentPanel.Size.Width / 2 - _glasses.Size.Width / 2, 3); _glasses.ValueChanged += (screen, args) => CalculateMax(); ContentPanel.Controls.Add(_glasses); - + _priceLabel = new Label("What price (in cents) do you wish to charge for lemonade?"); _priceLabel.Point = new Point(ContentPanel.Size.Width / 2 - _priceLabel.Content.Length / 2, 6); ContentPanel.Controls.Add(_priceLabel); @@ -46,7 +47,7 @@ namespace Lemonade _price.Point = new Point(ContentPanel.Size.Width / 2 - _price.Size.Width / 2, 7); _price.ValueChanged += (screen, args) => CalculateMax(); ContentPanel.Controls.Add(_price); - + _signsLabel = new Label("How many advertising signs do you want to make?"); _signsLabel.Point = new Point(ContentPanel.Size.Width / 2 - _signsLabel.Content.Length / 2, 10); ContentPanel.Controls.Add(_signsLabel); @@ -55,11 +56,11 @@ namespace Lemonade _signs.Point = new Point(ContentPanel.Size.Width / 2 - _signs.Size.Width / 2, 11); _signs.ValueChanged += (screen, args) => CalculateMax(); ContentPanel.Controls.Add(_signs); - + _infoLabelBottom = new Label("Total Expenses: 0/0"); _infoLabelBottom.Point = new Point(ContentPanel.Size.Width / 2 - _infoLabelBottom.Content.Length / 2, 14); ContentPanel.Controls.Add(_infoLabelBottom); - + Button okButton = new Button("OK"); okButton.Point = new Point(ContentPanel.Size.Width / 2 - okButton.Size.Width / 2, 16); okButton.Click += (sender, e) => Ok?.Invoke(_glasses.Value, 10, 0); @@ -68,7 +69,10 @@ namespace Lemonade Close += (screen, args) => Ok?.Invoke(_glasses.Value, 10, 0); } - public void SetUp(PlayerState player, Settings settings, int playerIndex, int day, Weather weather, int signCost, int lemonadeCost) + public event OkDelegate Ok; + + public void SetUp(PlayerState player, Settings settings, int playerIndex, int day, Weather weather, + int signCost, int lemonadeCost) { TabPoint = 0; _signCost = signCost; @@ -90,9 +94,9 @@ namespace Lemonade private void CalculateMax() { int leftover = _player.Budget - CalculateExpenses(); - _glasses.MaxValue = (int)Math.Floor(leftover / (double)_lemonadeCost) + _glasses.Value; + _glasses.MaxValue = (int) Math.Floor(leftover / (double) _lemonadeCost) + _glasses.Value; _price.MaxValue = 200; - _signs.MaxValue = (int)Math.Floor(leftover / (double)_signCost) + _signs.Value; + _signs.MaxValue = (int) Math.Floor(leftover / (double) _signCost) + _signs.Value; _infoLabelBottom.Content = $"Leftover: ${leftover / 100f}/${_player.Budget / 100f}"; _infoLabelBottom.Point = new Point(ContentPanel.Size.Width / 2 - _infoLabelBottom.Content.Length / 2, 14); } diff --git a/Lemonade/Weather.cs b/Lemonade/Weather.cs index 32d427e..11284c7 100644 --- a/Lemonade/Weather.cs +++ b/Lemonade/Weather.cs @@ -4,8 +4,9 @@ namespace Lemonade { public class Weather { - private static Random rnd = new Random(); - public override string ToString() => W.ToString().Replace('_', ' '); + private static readonly Random rnd = new Random(); + + public double Factor = rnd.NextDouble(); public W W { @@ -19,7 +20,7 @@ namespace Lemonade } } - public double Factor = rnd.NextDouble(); + public override string ToString() => W.ToString().Replace('_', ' '); } public enum W