From 26131b1c4df46a9fd4c41cecf3726de00f85b33e Mon Sep 17 00:00:00 2001
From: JFronny <33260128+JFronny@users.noreply.github.com>
Date: Fri, 12 Jun 2020 20:02:39 +0200
Subject: [PATCH] @ files
---
Lemonade/AnimationScreen.cs | 98 +++++++++++++++++++++++++++++-
Lemonade/Fakku.cs | 98 +++++++++++++++++++++++++++++-
Lemonade/GameState.cs | 4 +-
Lemonade/Image.cs | 11 +++-
Lemonade/Lemonade.csproj | 4 ++
Lemonade/PlayerState.cs | 35 ++++++++++-
Lemonade/Program.cs | 9 ++-
Lemonade/ResultScreen.cs | 42 ++++++++++++-
Lemonade/ScreenManager.cs | 108 +++++++++++++++++++++++++++++++++-
Lemonade/Settings.cs | 77 +++++++++++++++++++++++-
Lemonade/TransactionScreen.cs | 100 ++++++++++++++++++++++++++++++-
Lemonade/Weather.cs | 28 ++++++++-
12 files changed, 595 insertions(+), 19 deletions(-)
diff --git a/Lemonade/AnimationScreen.cs b/Lemonade/AnimationScreen.cs
index 7e20880..5f90472 100644
--- a/Lemonade/AnimationScreen.cs
+++ b/Lemonade/AnimationScreen.cs
@@ -1,7 +1,101 @@
+using System;
+using System.Drawing;
+using CC_Functions.Commandline.TUI;
+using CC_Functions.Misc;
+using static System.ConsoleColor;
+using static Lemonade.W;
+
namespace Lemonade
{
- public class AnimationScreen
+ public class AnimationScreen : CenteredScreen
{
-
+ public event OkDelegate Ok;
+ public delegate void OkDelegate();
+ private 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]);
+ SetWeather(new Weather());
+ ContentPanel.Controls.Add(imgControl);
+ Input += (screen, args) => Ok?.Invoke();
+ Close += (screen, args) => Ok?.Invoke();
+ }
+
+ public void SetWeather(Weather w)
+ {
+ Title = $"Lemonade - Weather: {w}";
+ //TODO weather events (storm (no sales), heat wave (more sales))
+ Pixel sky = new Pixel(w.W switch
+ {
+ Rainy => Black,
+ Cloudy => DarkBlue,
+ Warm => Blue,
+ Sunny => Blue,
+ Hot_and_dry => Magenta,
+ _ => throw new ArgumentOutOfRangeException()
+ }, Black, ' ');
+ Pixel grass = new Pixel(w.W switch
+ {
+ Rainy => Green,
+ Cloudy => Green,
+ Warm => Green,
+ Sunny => Green,
+ Hot_and_dry => Green,
+ _ => throw new ArgumentOutOfRangeException()
+ }, Black, ' ');
+ Pixel table = new Pixel(DarkGreen, Black, ' ');
+ Pixel glass = new Pixel(Yellow, Black, ' ');
+ Pixel sun = new Pixel(w.W switch
+ {
+ Rainy => Yellow,
+ Cloudy => Yellow,
+ Warm => Yellow,
+ Sunny => Yellow,
+ Hot_and_dry => Red,
+ _ => throw new ArgumentOutOfRangeException()
+ }, Black, ' ');
+ Pixel cloud = new Pixel(Gray, Black, ' ');
+ Pixel rain = new Pixel(DarkBlue, Black, ' ');
+ Pixel[,] image = new Pixel[20, 200];
+ //Draw sky
+ image.Populate(sky);
+ //Draw rain
+ Random rainRng = new Random(100);
+ if (w.W == Rainy)
+ for (int i = 2; i < 12; i++)
+ for (int j = 0; j < 200; j++)
+ if (rainRng.NextDouble() < 0.1)
+ {
+ image[i, j] = rain;
+ image[i + 1, j] = rain;
+ }
+ //Draw floor
+ for (int i = 13; i < 20; i++)
+ for (int j = 0; j < 200; j++)
+ image[i, j] = grass;
+ //Draw table
+ for (int i = 12; i < 16; i++)
+ for (int j = 40; j < 60; j++)
+ image[i, j] = table;
+ //Draw glasses
+ for (int j = 43; j < 57; j += 4)
+ {
+ image[11, j] = glass;
+ image[11, j + 1] = glass;
+ }
+ //Draw sun
+ if (w.W != Rainy && w.W != Cloudy)
+ image.DrawEllipse(new Rectangle(2, 1, 14, 6), sun);
+ //Draw clouds
+ if (w.W == Rainy || w.W == Cloudy)
+ {
+ image.DrawEllipse(new Rectangle(8, 1, 25, 3), cloud);
+ image.DrawEllipse(new Rectangle(40, 3, 40, 3), cloud);
+ }
+ //Set image
+ imgControl.Img = image;
+ }
}
}
\ No newline at end of file
diff --git a/Lemonade/Fakku.cs b/Lemonade/Fakku.cs
index 9b781fd..4316803 100644
--- a/Lemonade/Fakku.cs
+++ b/Lemonade/Fakku.cs
@@ -1,4 +1,98 @@
-$HEADER$namespace $NAMESPACE$
+using System;
+using System.Drawing;
+using CC_Functions.Commandline.TUI;
+
+namespace Lemonade
{
- public class $CLASS$ {$END$}
+ 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));
+
+ public static void DrawEllipse(this Pixel[,] target, Rectangle area, Pixel basePixel)
+ {
+ int p0 = target.GetLength(0);
+ int p1 = target.GetLength(1);
+ bool[,] tmp = new bool[p0, p1];
+ DrawEllipse(tmp, new Rectangle(area.Y, area.X, area.Height, area.Width));
+ for (int i = 0; i < p0; i++)
+ for (int j = 0; j < p1; j++)
+ if (tmp[i, j])
+ target[i, j] = basePixel;
+ }
+
+ 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;
+ if (xPos < 0 || rxPos < xPos || xPos >= matrixWidth) continue;
+ 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;
+ if (yPos >= 0)
+ {
+ if (xPos < matrixWidth && yPos < matrixHeight) pixels[xPos, yPos] = 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;
+ if (rxPos < matrixWidth)
+ {
+ if(jPos > -1 && jPos < matrixHeight) pixels[rxPos, jPos] = true;
+ if(rjPos > -1 && rjPos < matrixHeight) pixels[rxPos, rjPos] = true;
+ }
+ }
+ firstRun = false;
+ prevY = y;
+ float countTarget = radiusY - y;
+ for (int count = 0; count < countTarget; ++count)
+ {
+ ++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 (rxPos < matrixWidth)
+ {
+ if(yPos > -1 && yPos < matrixHeight) pixels[rxPos, yPos] = true;
+ if(ryPos > -1 && ryPos < matrixHeight) pixels[rxPos, ryPos] = true;
+ }
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/Lemonade/GameState.cs b/Lemonade/GameState.cs
index 3b75f88..ff48c89 100644
--- a/Lemonade/GameState.cs
+++ b/Lemonade/GameState.cs
@@ -2,6 +2,8 @@ namespace Lemonade
{
public enum GameState
{
-
+ Setup,
+ Transaction,
+ Event
}
}
\ No newline at end of file
diff --git a/Lemonade/Image.cs b/Lemonade/Image.cs
index defad5d..bd09869 100644
--- a/Lemonade/Image.cs
+++ b/Lemonade/Image.cs
@@ -1,7 +1,14 @@
+using CC_Functions.Commandline.TUI;
+
namespace Lemonade
{
- public class Image
+ public class Image : Control
{
-
+ public Pixel[,] Img;
+ public Image(Pixel[,] img) => Img = img;
+
+ public override Pixel[,] Render() => Img;
+
+ public override bool Selectable { get; } = false;
}
}
\ No newline at end of file
diff --git a/Lemonade/Lemonade.csproj b/Lemonade/Lemonade.csproj
index 2c0dacc..8659fff 100644
--- a/Lemonade/Lemonade.csproj
+++ b/Lemonade/Lemonade.csproj
@@ -5,4 +5,8 @@
netcoreapp3.1
+
+
+
+
diff --git a/Lemonade/PlayerState.cs b/Lemonade/PlayerState.cs
index b35ede5..986988b 100644
--- a/Lemonade/PlayerState.cs
+++ b/Lemonade/PlayerState.cs
@@ -1,4 +1,35 @@
-$HEADER$namespace $NAMESPACE$
+using System;
+
+namespace Lemonade
{
- public struct $STRUCT$ {$END$}
+ 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 Number;
+
+ public PlayerState(int number)
+ {
+ Budget = 200;
+ Number = number;
+ }
+
+ 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
+
+ Budget += Earnings - Expenses;
+ }
+ }
}
\ No newline at end of file
diff --git a/Lemonade/Program.cs b/Lemonade/Program.cs
index d130e09..1a7ba7f 100644
--- a/Lemonade/Program.cs
+++ b/Lemonade/Program.cs
@@ -6,7 +6,12 @@ namespace Lemonade
{
static void Main(string[] args)
{
- Console.WriteLine("Hello World!");
+ Console.BackgroundColor = ConsoleColor.Black;
+ Console.ForegroundColor = ConsoleColor.White;
+ Settings settings = new Settings();
+ ScreenManager screenManager = new ScreenManager(settings);
+ screenManager.Run();
+ Console.ResetColor();
}
}
-}
+}
\ No newline at end of file
diff --git a/Lemonade/ResultScreen.cs b/Lemonade/ResultScreen.cs
index 9b781fd..8c2d778 100644
--- a/Lemonade/ResultScreen.cs
+++ b/Lemonade/ResultScreen.cs
@@ -1,4 +1,42 @@
-$HEADER$namespace $NAMESPACE$
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using CC_Functions.Commandline;
+using CC_Functions.Commandline.TUI;
+
+namespace Lemonade
{
- public class $CLASS$ {$END$}
+ public class ResultScreen : CenteredScreen
+ {
+ public event OkDelegate Ok;
+ public delegate void OkDelegate();
+ private Label lab;
+ public ResultScreen(Settings settings) : base(200, 20, ConsoleColor.Black, settings.Color)
+ {
+ ContentPanel.ForeColor = ConsoleColor.DarkGray;
+ Title = "Lemonade - Daily financial report";
+ lab = new Label("");
+ ContentPanel.Controls.Add(lab);
+ Input += (screen, args) => Ok?.Invoke();
+ Close += (screen, args) => Ok?.Invoke();
+ }
+
+ 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.Render();
+ ActualSize = new Size(lab.Size.Width, lab.Size.Height);
+ }
+ }
}
\ No newline at end of file
diff --git a/Lemonade/ScreenManager.cs b/Lemonade/ScreenManager.cs
index ab10c8e..2972929 100644
--- a/Lemonade/ScreenManager.cs
+++ b/Lemonade/ScreenManager.cs
@@ -1,7 +1,113 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using CC_Functions.Commandline.TUI;
+
namespace Lemonade
{
+ //TODO implement thunderstorm chance on bad weather
public class ScreenManager
{
-
+ private readonly AnimationScreen _animator;
+ 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 Weather _weather;
+ private int signCost => 15;
+ private int GlassCost => _day < 5 ? 2 : 4;
+
+ public ScreenManager(Settings settings)
+ {
+ _settings = settings;
+ _animator = new AnimationScreen(settings);
+ _animator.Ok += () =>
+ {
+ _state = GameState.Transaction;
+ _currentPlayer = 0;
+ _initialEvent = true;
+ _transaction.SetUp(_players[_currentPlayer], _settings, _currentPlayer, _day, _weather, signCost, GlassCost);
+ };
+ _transaction = new TransactionScreen(settings);
+ _transaction.Ok += (glasses, price, signs) =>
+ {
+ _initialEvent = true;
+ _players[_currentPlayer].Glasses = glasses;
+ _players[_currentPlayer].GlassPrice = price;
+ _players[_currentPlayer].Signs = signs;
+ _players[_currentPlayer].CalculateIncome(signCost, GlassCost, _weather, settings);
+ _currentPlayer++;
+ if (_currentPlayer >= _players.Count)
+ {
+ _state = GameState.Event;
+ _currentPlayer = 0;
+ }
+ else
+ {
+ _transaction.Tab(true);
+ _transaction.Tab(false);
+ }
+ };
+ _result = new ResultScreen(settings);
+ _result.Ok += () =>
+ {
+ _initialEvent = true;
+ _state = GameState.Setup;
+ };
+ _state = GameState.Setup;
+ _players = new List();
+ for (int i = 0; i < settings.PlayerCount; i++) _players.Add(new PlayerState(i + 1));
+ }
+
+ public void Run()
+ {
+ _running = true;
+ _state = GameState.Setup;
+ while (_running)
+ {
+ switch (_state)
+ {
+ case GameState.Setup:
+ if (_initialEvent)
+ {
+ _day++;
+ _weather = new Weather();
+ _animator.SetWeather(_weather);
+ _animator.Render();
+ _initialEvent = false;
+ }
+ _animator.ReadInput();
+ Thread.Sleep(100);
+ break;
+ case GameState.Transaction:
+ if (_initialEvent)
+ {
+ _transaction.SetUp(_players[_currentPlayer], _settings, _currentPlayer, _day, _weather, signCost, GlassCost);
+ _transaction.Render();
+ _initialEvent = false;
+ }
+ _transaction.ReadInput();
+ Thread.Sleep(100);
+ break;
+ case GameState.Event:
+ if (_initialEvent)
+ {
+ _result.Setup(_players);
+ _result.Render();
+ _initialEvent = false;
+ }
+ _result.ReadInput();
+ Thread.Sleep(100);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/Lemonade/Settings.cs b/Lemonade/Settings.cs
index 9b781fd..2892f35 100644
--- a/Lemonade/Settings.cs
+++ b/Lemonade/Settings.cs
@@ -1,4 +1,77 @@
-$HEADER$namespace $NAMESPACE$
+using System;
+using System.Drawing;
+using System.Threading;
+using CC_Functions.Commandline.TUI;
+
+namespace Lemonade
{
- public class $CLASS$ {$END$}
+ 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 void Configure()
+ {
+ CenteredScreen settingsScreen = new CenteredScreen(200, 20, ConsoleColor.Black, Color)
+ {
+ TabPoint = 0,
+ Title = "Lemonade - Settings"
+#if DEBUG
+ + "[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);
+
+ 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);
+
+ Slider difficulty = new Slider {Value = 5, Size = new Size(100, 1)};
+ difficulty.Point = new Point(scr.Size.Width / 2 - difficulty.Size.Width / 2, 8);
+ scr.Controls.Add(difficulty);
+
+ 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;
+ };
+#if DEBUG
+ 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)
+ {
+ settingsScreen.ReadInput();
+ Thread.Sleep(100);
+ }
+ PlayerCount = playerSlider.Value;
+ DifficultyFactor = difficulty.Value / 10f;
+ Color = colorBox.Checked;
+ }
+ }
}
\ No newline at end of file
diff --git a/Lemonade/TransactionScreen.cs b/Lemonade/TransactionScreen.cs
index 7035a04..d267473 100644
--- a/Lemonade/TransactionScreen.cs
+++ b/Lemonade/TransactionScreen.cs
@@ -1,7 +1,103 @@
+using System;
+using System.Diagnostics.Contracts;
+using System.Drawing;
+using CC_Functions.Commandline.TUI;
+
namespace Lemonade
{
- public class TransactionScreen
+ 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 _infoLabelBottom;
+ 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);
+
+ _price = new Slider {Size = new Size(100, 1)};
+ _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);
+
+ _signs = new Slider {Size = new Size(100, 1)};
+ _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);
+ ContentPanel.Controls.Add(okButton);
+
+ 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)
+ {
+ TabPoint = 0;
+ _signCost = signCost;
+ _lemonadeCost = lemonadeCost;
+ Title = $"Lemonade - Player {playerIndex + 1}/{settings.PlayerCount}";
+ _player = player;
+ _glasses.Value = 0;
+ _price.Value = 0;
+ _signs.Value = 0;
+ CalculateMax();
+ _infoLabel.Content = $"It is day {day}, the weather is {weather}";
+ _infoLabel.Point = new Point(ContentPanel.Size.Width / 2 - _infoLabel.Content.Length / 2, 0);
+ _glassesLabel.Content = $"How many glasses of lemonade do you wish to make? {lemonadeCost}ct each";
+ _glassesLabel.Point = new Point(ContentPanel.Size.Width / 2 - _glassesLabel.Content.Length / 2, 2);
+ _signsLabel.Content = $"How many advertising signs ({signCost}ct each) do you want to make?";
+ _signsLabel.Point = new Point(ContentPanel.Size.Width / 2 - _signsLabel.Content.Length / 2, 10);
+ }
+
+ private void CalculateMax()
+ {
+ int leftover = _player.Budget - CalculateExpenses();
+ _glasses.MaxValue = (int)Math.Floor(leftover / (double)_lemonadeCost) + _glasses.Value;
+ _price.MaxValue = 200;
+ _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);
+ }
+
+ [Pure]
+ private int CalculateExpenses() => _lemonadeCost * _glasses.Value + _signCost * _signs.Value;
}
}
\ No newline at end of file
diff --git a/Lemonade/Weather.cs b/Lemonade/Weather.cs
index 1f6690d..32d427e 100644
--- a/Lemonade/Weather.cs
+++ b/Lemonade/Weather.cs
@@ -1,7 +1,33 @@
+using System;
+
namespace Lemonade
{
public class Weather
{
-
+ private static Random rnd = new Random();
+ public override string ToString() => W.ToString().Replace('_', ' ');
+
+ public W W
+ {
+ get
+ {
+ if (Factor < 0.2) return W.Rainy;
+ if (Factor < 0.4) return W.Cloudy;
+ if (Factor < 0.6) return W.Warm;
+ if (Factor < 0.8) return W.Sunny;
+ return W.Hot_and_dry;
+ }
+ }
+
+ public double Factor = rnd.NextDouble();
+ }
+
+ public enum W
+ {
+ Rainy,
+ Cloudy,
+ Warm,
+ Sunny,
+ Hot_and_dry
}
}
\ No newline at end of file