Compare commits

..

10 Commits

Author SHA1 Message Date
44ddb1fbec Math functions implementation 2023-12-26 13:37:55 +06:00
19a1ddb334 unit tests 2023-12-26 01:39:41 +06:00
7cf49a5a1b uml diagrams 2023-12-26 01:19:24 +06:00
c9447cebdf fixed bugs 2023-12-26 00:28:56 +06:00
4ebb81c211 icon 2023-12-25 21:49:06 +06:00
04d258c5a3 app logic restored 2023-12-25 21:40:40 +06:00
bf2c734baf code simplified 2023-12-25 18:53:46 +06:00
86b9afe02f Merge branch 'fattakh_version_but_good' into fattakh
# Conflicts:
#	SharpCalculator.Avalonia/MainWindow.axaml
#	SharpCalculator.Avalonia/MainWindow.axaml.cs
2023-12-25 18:23:16 +06:00
e8959b9498 latest fixes from Fattakh 2023-12-25 18:19:04 +06:00
c7eda63c03 styles 2023-12-25 18:14:09 +06:00
16 changed files with 3724 additions and 630 deletions

@ -1 +1 @@
Subproject commit 2a4f92fe351882a489c330ba82504d319df14c73 Subproject commit d83106358fbf7293a112d6f3c75f6113e546aa09

View File

@ -3,6 +3,31 @@
x:Class="SharpCalculator.Avalonia.App" x:Class="SharpCalculator.Avalonia.App"
RequestedThemeVariant="Dark"> RequestedThemeVariant="Dark">
<Application.Styles> <Application.Styles>
<SimpleTheme /> <SimpleTheme />
<Style Selector="Control.center">
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style Selector="Button.cirlce">
<Setter Property="Height" Value="60"/>
<Setter Property="Width" Value="60"/>
<Setter Property="CornerRadius" Value="30"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>
<Style Selector="Button.gray">
<Setter Property="Background" Value="Gray"/>
</Style>
<Style Selector="Button.orange">
<Setter Property="Background" Value="#C07500"/>
</Style>
</Application.Styles> </Application.Styles>
</Application> </Application>

View File

@ -1,4 +1,10 @@
using Avalonia; global using System;
global using System.Collections.Generic;
global using System.Globalization;
global using Avalonia;
global using Avalonia.Controls;
global using Avalonia.Interactivity;
global using Avalonia.Media;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;

View File

@ -1,571 +1,162 @@
<Window <Window
FontFamily="Consolas"
FontSize="24"
Height="750"
Title="SharpCalculator"
Width="600"
mc:Ignorable="d"
x:Class="SharpCalculator.Avalonia.MainWindow"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Class="SharpCalculator.Avalonia.MainWindow"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> Title="SharpCalculator"
Icon="avares://SharpCalculator.Avalonia/assets/icon.ico"
FontFamily="Consolas" FontSize="24"
Width="460" Height="570">
<Grid <Grid Margin="10">
HorizontalAlignment="Center" <Grid.RowDefinitions>1* 40 1* 330</Grid.RowDefinitions>
Margin="20"
VerticalAlignment="Center"> <TextBox Name="Input" Grid.Row="0"
TextChanged="Input_OnTextChanged"
BorderThickness="2"
BorderBrush="#AAAAAA"
TextWrapping="Wrap"/>
<TextBlock Grid.Row="1"
VerticalAlignment="Center"
Foreground="#AAAAAA"
Text="="/>
<TextBox Name="Output" Grid.Row="1"
Margin="16 0 0 0"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
IsReadOnly="True"
BorderThickness="0"
TextWrapping="NoWrap"/>
<TextBox Name="History" Grid.Row="2"
Foreground="Gray"
BorderThickness="1"
BorderBrush="Gray"
IsReadOnly="True"
TextWrapping="NoWrap"
FontSize="18"/>
<Grid Grid.Row="3" VerticalAlignment="Bottom"
MinWidth="440" MaxWidth="440" MinHeight="320" MaxHeight="320">
<Grid.ColumnDefinitions>* * * * * * *</Grid.ColumnDefinitions> <Grid.ColumnDefinitions>* * * * * * *</Grid.ColumnDefinitions>
<Grid.RowDefinitions>* * * * *</Grid.RowDefinitions>
<Grid.RowDefinitions>* * * * * * * * * *</Grid.RowDefinitions>
<!-- 1st row --> <!-- 1st row -->
<TextBlock <Button Classes="cirlce gray" Grid.Column="0" Grid.Row="0"
FontSize="40" Click="ClearButton_OnClick" Content="AC"/>
Grid.Column="0"
Grid.ColumnSpan="7" <Button Classes="cirlce gray" Grid.Column="1" Grid.Row="0"
Grid.Row="1" Click="MathButton_OnClick" Content="("/>
HorizontalAlignment="Right"
Name="Input" <Button Classes="cirlce gray" Grid.Column="2" Grid.Row="0"
Text="" /> Click="MathButton_OnClick" Content=")" />
<Button Classes="cirlce orange" Grid.Column="3" Grid.Row="0"
Click="MathButton_OnClick" Content="/"/>
<Button Classes="cirlce gray" Grid.Column="4" Grid.Row="0"
Click="MathButton_OnClick" Content="1/x"/>
<Button Classes="cirlce gray" Grid.Column="5" Grid.Row="0"
Click="MathButton_OnClick" Content="sin"/>
<Button Classes="cirlce gray" Grid.Column="6" Grid.Row="0"
Click="MathButton_OnClick" Content="asin"/>
<!-- 2nd row --> <!-- 2nd row -->
<Button <Button Classes="cirlce" Grid.Column="0" Grid.Row="1"
Background="Gray" Click="MathButton_OnClick" Content="7"/>
Click="ClearButton_OnClick"
Content="AC"
Grid.Column="0"
Grid.Row="2"
Name="ClearButton"/>
<Button <Button Classes="cirlce" Grid.Column="1" Grid.Row="1"
Background="Gray" Click="MathButton_OnClick" Content="8"/>
Click="MathButton_OnClick"
Content="("
CornerRadius="30"
Grid.Column="1"
Grid.Row="2"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button
Background="Gray"
Click="MathButton_OnClick"
Content=")"
CornerRadius="30"
Grid.Column="2"
Grid.Row="2"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button
Background="Orange"
Click="MathButton_OnClick"
Content="/"
CornerRadius="30"
Grid.Column="3"
Grid.Row="2"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce" Grid.Column="2" Grid.Row="1"
Background="Gray" Click="MathButton_OnClick" Content="9"/>
Click="MathButton_OnClick"
Content="^"
CornerRadius="30"
Grid.Column="4"
Grid.Row="2"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce orange" Grid.Column="3" Grid.Row="1"
Background="Gray" Click="MathButton_OnClick" Content="*"/>
Click="MathButton_OnClick"
Content="sin"
CornerRadius="30"
Grid.Column="5"
Grid.Row="2"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce gray" Grid.Column="4" Grid.Row="1"
Background="Gray" Click="MathButton_OnClick" Content="^"/>
Click="MathButton_OnClick"
Content="asin"
CornerRadius="30"
Grid.Column="6"
Grid.Row="2"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<!-- 3rd row --> <Button Classes="cirlce gray" Grid.Column="5" Grid.Row="1"
Click="MathButton_OnClick" Content="cos"/>
<Button <Button Classes="cirlce gray" Grid.Column="6" Grid.Row="1"
Click="MathButton_OnClick" Click="MathButton_OnClick" Content="acos"/>
Content="7"
CornerRadius="30"
Grid.Column="0"
Grid.Row="3"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <!-- 3th row -->
Click="MathButton_OnClick"
Content="8"
CornerRadius="30"
Grid.Column="1"
Grid.Row="3"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button
Click="MathButton_OnClick"
Content="9"
CornerRadius="30"
Grid.Column="2"
Grid.Row="3"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button
Background="Orange"
Click="MathButton_OnClick"
Content="*"
CornerRadius="30"
Grid.Column="3"
Grid.Row="3"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce" Grid.Column="0" Grid.Row="2"
Background="Gray" Click="MathButton_OnClick" Content="4"/>
Click="MathButton_OnClick"
Content="e"
CornerRadius="30"
Grid.Column="4"
Grid.Row="3"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce" Grid.Column="1" Grid.Row="2"
Background="Gray" Click="MathButton_OnClick" Content="5"/>
Click="MathButton_OnClick"
Content="cos"
CornerRadius="30"
Grid.Column="5"
Grid.Row="3"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce" Grid.Column="2" Grid.Row="2"
Background="Gray" Click="MathButton_OnClick" Content="6"/>
Click="MathButton_OnClick"
Content="acos" <Button Classes="cirlce orange" Grid.Column="3" Grid.Row="2"
CornerRadius="30" Click="MathButton_OnClick" Content="-"/>
Grid.Column="6"
Grid.Row="3" <Button Classes="cirlce gray" Grid.Column="4" Grid.Row="2"
Height="60" FontSize="22"
HorizontalAlignment="Center" Click="MathButton_OnClick" Content="10^x"/>
HorizontalContentAlignment="Center"
Margin="5" <Button Classes="cirlce gray" Grid.Column="5" Grid.Row="2"
VerticalAlignment="Center" Click="MathButton_OnClick" Content="tg"/>
VerticalContentAlignment="Center"
Width="60" /> <Button Classes="cirlce gray" Grid.Column="6" Grid.Row="2"
Click="MathButton_OnClick" Content="atg"/>
<!-- 4th row --> <!-- 4th row -->
<Button <Button Classes="cirlce" Grid.Column="0" Grid.Row="3"
Click="MathButton_OnClick" Click="MathButton_OnClick" Content="1"/>
Content="4"
CornerRadius="30"
Grid.Column="0"
Grid.Row="4"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce" Grid.Column="1" Grid.Row="3"
Click="MathButton_OnClick" Click="MathButton_OnClick" Content="2"/>
Content="5"
CornerRadius="30"
Grid.Column="1"
Grid.Row="4"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce" Grid.Column="2" Grid.Row="3"
Click="MathButton_OnClick" Click="MathButton_OnClick" Content="3"/>
Content="6"
CornerRadius="30"
Grid.Column="2"
Grid.Row="4"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce orange" Grid.Column="3" Grid.Row="3"
Background="Orange" Click="MathButton_OnClick" Content="+"/>
Click="MathButton_OnClick"
Content="-"
CornerRadius="30"
Grid.Column="3"
Grid.Row="4"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce gray" Grid.Column="4" Grid.Row="3"
Background="Gray" Click="MathButton_OnClick" Content="e"/>
Click="MathButton_OnClick"
Content="10^x"
CornerRadius="30"
Grid.Column="4"
Grid.Row="4"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce gray" Grid.Column="5" Grid.Row="3"
Background="Gray" Click="MathButton_OnClick" Content="ctg"/>
Click="MathButton_OnClick"
Content="tan"
CornerRadius="30"
Grid.Column="5"
Grid.Row="4"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce gray" Grid.Column="6" Grid.Row="3"
Background="Gray" Click="MathButton_OnClick" Content="actg"/>
Click="MathButton_OnClick"
Content="atan"
CornerRadius="30"
Grid.Column="6"
Grid.Row="4"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<!-- 5th row --> <!-- 5th row -->
<Button <Button Classes="cirlce" Grid.Column="0" Grid.Row="4"
Click="MathButton_OnClick" Click="MathButton_OnClick" Content="0"/>
Content="1"
CornerRadius="30"
Grid.Column="0"
Grid.Row="5"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce" Grid.Column="1" Grid.Row="4"
Click="MathButton_OnClick" Click="MathButton_OnClick" Content="."/>
Content="2"
CornerRadius="30"
Grid.Column="1"
Grid.Row="5"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce" Grid.Column="2" Grid.Row="4"
Click="MathButton_OnClick" Click="MathButton_OnClick" Content="%"/>
Content="3"
CornerRadius="30"
Grid.Column="2"
Grid.Row="5"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce orange" Grid.Column="3" Grid.Row="4"
Background="Orange" Click="ResultButton_OnClick" Content="="/>
Click="MathButton_OnClick"
Content="+"
CornerRadius="30"
Grid.Column="3"
Grid.Row="5"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce gray" Grid.Column="4" Grid.Row="4"
Background="Gray" Click="MathButton_OnClick" Content="π"/>
Click="MathButton_OnClick"
Content="rand"
CornerRadius="30"
Grid.Column="4"
Grid.Row="5"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce gray" Grid.Column="5" Grid.Row="4"
Background="Gray" FontSize="22"
Click="MathButton_OnClick" Click="MathButton_OnClick" Content="rand"/>
Content="ctg"
CornerRadius="30"
Grid.Column="5"
Grid.Row="5"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button <Button Classes="cirlce gray" Grid.Column="6" Grid.Row="4"
Background="Gray" Click="MathButton_OnClick" Content="ln"/>
Click="MathButton_OnClick" </Grid>
Content="actg"
CornerRadius="30"
Grid.Column="6"
Grid.Row="5"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<!-- 6th row -->
<Button
Click="MathButton_OnClick"
Content="0"
CornerRadius="30"
Grid.Column="0"
Grid.Row="6"
Height="55"
HorizontalContentAlignment="Center"
Margin="5"
VerticalContentAlignment="Center"
Width="60" />
<Button
Click="MathButton_OnClick"
Content="%"
CornerRadius="30"
Grid.Column="1"
Grid.Row="6"
Height="55"
HorizontalContentAlignment="Center"
Margin="5"
VerticalContentAlignment="Center"
Width="60" />
<Button
Click="MathButton_OnClick"
Content="."
CornerRadius="30"
Grid.Column="2"
Grid.Row="6"
Height="55"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button
Background="Orange"
Click="ResultButton_OnClick"
Content="="
CornerRadius="30"
Grid.Column="3"
Grid.Row="6"
Height="55"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button
Background="Gray"
Click="MathButton_OnClick"
Content="π"
CornerRadius="30"
Grid.Column="4"
Grid.Row="6"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button
Background="Gray"
Click="MathButton_OnClick"
Content="1/x"
CornerRadius="30"
Grid.Column="5"
Grid.Row="6"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<Button
Background="Gray"
Click="MathButton_OnClick"
Content="log"
CornerRadius="30"
Grid.Column="6"
Grid.Row="6"
Height="60"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Margin="5"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="60" />
<!-- 7th row -->
<TextBlock
FontSize="25"
Grid.Column="0"
Grid.ColumnSpan="7"
Grid.Row="7"
Name="History1"
Text="" />
<!-- 8th row -->
<TextBlock
FontSize="25"
Grid.Column="0"
Grid.ColumnSpan="7"
Grid.Row="8"
Name="History2"
Text="" />
<!-- 9th row -->
<TextBlock
FontSize="25"
Grid.Column="0"
Grid.ColumnSpan="7"
Grid.Row="9"
Name="History3"
Text="" />
</Grid> </Grid>
</Window> </Window>

View File

@ -1,129 +1,106 @@
// This implementation of the calculator using
// multi-translating programming language Fusion.
// The main logic was written on the Fusion,
// then retranslated into c#, 'out' module in FusionCalculator
// is a translated c# code, that used by SharpCalculator module.
// If you want to dive into the logic of the calculator,
// you need to check 'out' folder in FusionCalculator module.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Interactivity;
using FusionCalculator; using FusionCalculator;
using Avalonia.Media;
namespace SharpCalculator.Avalonia; namespace SharpCalculator.Avalonia;
public partial class MainWindow : Window public partial class MainWindow : Window
{ {
static Random _random = new Random(); // Random object for rand() function in calculator private readonly Random Random = new();
double _randomNumber = _random.NextDouble(); // Random variable is between 0 to 1
private int _currentIndex = 0; // Current index for checking the length of input text, accordingly for clear button
private List<string> _history = new List<string>();
public MainWindow() public MainWindow()
{ {
InitializeComponent(); InitializeComponent();
} }
private void AppendToHistory(string line) //function of appending expression to the history list
{
// begin new line if not empty
if (!string.IsNullOrEmpty(History.Text))
History.Text += '\n';
/// add line without space characters
History.Text += line
.Replace("\t", " ")
.Replace("\n", " ")
.Replace("\r", " ")
.Replace(" ", " ");
}
private void MathButton_OnClick(object? sender, RoutedEventArgs e) private void MathButton_OnClick(object? sender, RoutedEventArgs e)
{ {
if (sender is not Button button) // Checking if button exist, if not throw Exception if (sender is not Button button)
throw new Exception(); throw new Exception();
string text; // declaring text for using it in switch case string buttonText = button.Content!.ToString()!; // declaring text for using it in switch case
Input.Text += buttonText switch
ClearButton.Content = "AC"; // clear button content changing to Accurate Clear mode
switch (Input.Text) // Switch case for checking the inputting functions
{ {
case "rand": // rand function add random variable from 0 to 1 into Input "rand" => // random number from 0 to 1 into Input
Input.Text = ""; Random.NextDouble().ToString("0.#####", CultureInfo.InvariantCulture),
Input.Text += _randomNumber.ToString(CultureInfo.InvariantCulture); "π" => // Pi constant
break; "3.14159",
case "π": // Pi function add pi value into Input "e" => // E constant
Input.Text = ""; "2.71828",
Input.Text += "3.1415"; "10^x" => // ten in power of x function
break; "10^",
case "e": // euler function add e value into Input "1/x" => // one over x function
Input.Text = ""; "1/",
Input.Text += "2.71828"; "sin" or "cos" or "tg" or "ctg"
break; or "asin" or "acos" or "atg" or "actg"
case "10^x": // ten in power of x function or "ln" => buttonText+'(',
Input.Text = ""; _ => buttonText
Input.Text += "10^"; };
break;
case "1/x": // one over x function
Input.Text = "";
Input.Text += "1/";
break;
default: // if there is no function input, then just input Button content
text = button.Content!.ToString()!;
Input.Text += text;
break;
}
} }
private void ClearButton_OnClick(object? sender, RoutedEventArgs e) private void ClearButton_OnClick(object? sender, RoutedEventArgs e)
{
// Checking the indexes and the emptiness of the input for clearing one by one
if (Input.Text != "" && _currentIndex < Input.Text!.Length)
{
if ((string)ClearButton.Content! == "AC") // if clear button content equal to AC, clear one by one
{
Input.Text = Input.Text.Remove(_currentIndex, 1);
_currentIndex++;
}
else if ((string)ClearButton.Content! == "C") // if clear button content equal to C, clear all
{ {
Input.Text = ""; Input.Text = "";
Output.Text = "";
} }
}
else private void UndoButton_OnClick(object? sender, RoutedEventArgs e)
{ {
// Handle the case when there's no text or all characters are cleared // delete last digit
_currentIndex = 0; // Reset the index for the next round // if (!string.IsNullOrEmpty(Input.Text))
} // Input.Text = Input.Text.Remove(Input.Text.Length - 1);
Input.Undo();
} }
private void ResultButton_OnClick(object? sender, RoutedEventArgs e) private void ResultButton_OnClick(object? sender, RoutedEventArgs e)
{ {
History1.Foreground = new SolidColorBrush(Colors.Gray); if(Input.Text == null || Output.Text == null || Output.Text.StartsWith("Error"))
History2.Foreground = new SolidColorBrush(Colors.Gray);
History3.Foreground = new SolidColorBrush(Colors.Gray);
if(Input.Text == null) // checking Input for nullability
return; return;
string exprStr = Input.Text; // expression variable, for print result string expression = Input.Text;
string result = Output.Text;
AppendToHistory($"{expression}={result}");
Input.Text = result;
}
private void Input_OnTextChanged(object? sender, TextChangedEventArgs e)
{
if(Input.Text == null)
return;
string exprStr = Input.Text; // mathematical expression
try try
{ {
double rezult = Calculator.Calculate(exprStr); // result being processed by calculator object that implemented in FusionCalculator Module // expression is being processed by Calculator class that implemented in FusionCalculator Module
if (!double.IsNaN(rezult)) double result = Calculator.Calculate(exprStr);
// incomplete expression with no rezult
if (double.IsNaN(result))
Output.Text = "";
else if (Math.Abs(result) is >= 10e-5 and <= 10e15)
{ {
Input.Text = rezult.ToString(CultureInfo.InvariantCulture); // decimal number with 5-digit precision for regular numbers
_history.Add(rezult.ToString(CultureInfo.InvariantCulture)); Output.Text = result.ToString("0.#####", CultureInfo.InvariantCulture);
}
else
{
// scientific notation with 5-digit precision for big and small numbers
Output.Text = result.ToString("0.#####E0", CultureInfo.InvariantCulture);
} }
} }
catch (Exception exception) catch (Exception exception)
{ {
Input.Text = "Error: "+exception.Message; Output.Text = $"Error: {exception.Message}";
} }
// Display the calculation history in the three TextBlocks
if (_history.Count > 0)
History1.Text = _history[0];
if (_history.Count > 1)
History2.Text = _history[1];
if (_history.Count > 2)
History3.Text = _history[2];
ClearButton.Content = "C"; // if the expression is printed, then change clear button content ot C, for clearing expression totally
} }
} }

View File

@ -6,9 +6,6 @@ namespace SharpCalculator.Avalonia;
class Program class Program
{ {
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread] [STAThread]
public static void Main(string[] args) public static void Main(string[] args)
{ {

View File

@ -7,6 +7,7 @@
<ImplicitUsings>disable</ImplicitUsings> <ImplicitUsings>disable</ImplicitUsings>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport> <BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault> <AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<ApplicationIcon>assets\icon.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -19,4 +20,8 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FusionCalculator\FusionCalculator.csproj" /> <ProjectReference Include="..\FusionCalculator\FusionCalculator.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<AvaloniaResource Include="assets\**"/>
</ItemGroup>
</Project> </Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@ -0,0 +1,35 @@
namespace SharpCalculator.Tests;
public class ComplicatedExpressionTests
{
public ComplicatedExpressionTests()
{
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
}
[Theory]
[InlineData(0.9,2,3)]
public void Expression1(double a, double b, double c) =>
Assert.Equal( a/(b+c), Calculator.Calculate($"({a})/(({b})+({c}))"));
[Theory]
[InlineData(0.9,2,3)]
public void Expression2(double a, double b, double c) =>
Assert.Equal( Math.Sin(a)-b*Math.Cos(c),
Calculator.Calculate($"sin(({a}))-(({b})*cos(({c})))"),
FunctionTests.PRECISION);
[Theory]
[InlineData(0.9,2,3)]
public void Expression3(double a, double b, double c) =>
Assert.Equal( a*Math.Pow(b,c)+a*Math.Pow(b,c+1)+a*Math.Pow(b,c+2),
Calculator.Calculate($"({a})*({b})^({c}) + ({a})*({b})^({c+1}) + ({a})*({b})^({c+2})"),
FunctionTests.PRECISION);
[Theory]
[InlineData(0.9,2,3)]
public void Expression4(double a, double b, double c) =>
Assert.Equal(a/(b+Math.Tan(c)),
Calculator.Calculate($"({a})/(({b})+tan(({c})))"),
FunctionTests.PRECISION);
}

View File

@ -0,0 +1,107 @@
namespace SharpCalculator.Tests;
public class FunctionTests
{
public const int PRECISION = 8;
public FunctionTests()
{
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
}
[Theory]
[InlineData(5)]
[InlineData(1)]
[InlineData(-3)]
[InlineData(-2)]
[InlineData(Math.PI/4)]
[InlineData(Math.PI/2)]
[InlineData(Math.PI*3/4)]
[InlineData(Math.PI*2)]
[InlineData(999)]
[InlineData(-999)]
public void Sin(double a) =>
Assert.Equal(Math.Sin(a), Calculator.Calculate($"sin({a})"), PRECISION);
[Theory]
[InlineData(5)]
[InlineData(1)]
[InlineData(-3)]
[InlineData(-2)]
[InlineData(Math.PI/4)]
[InlineData(Math.PI/2)]
[InlineData(Math.PI*3/4)]
[InlineData(Math.PI*2)]
[InlineData(999)]
[InlineData(-999)]
public void Cos(double a) =>
Assert.Equal(Math.Cos(a), Calculator.Calculate($"cos({a})"), PRECISION);
[Theory]
[InlineData(5)]
[InlineData(1)]
[InlineData(-3)]
[InlineData(-2)]
[InlineData(Math.PI/4)]
[InlineData(Math.PI/1.99)]
[InlineData(Math.PI*3/4)]
[InlineData(Math.PI*1.99)]
[InlineData(999)]
[InlineData(-999)]
public void Tan(double a) =>
Assert.Equal(Math.Tan(a), Calculator.Calculate($"tan({a})"), PRECISION);
[Theory]
[InlineData(5)]
[InlineData(1)]
[InlineData(-3)]
[InlineData(-2)]
[InlineData(Math.PI/4)]
[InlineData(Math.PI/2)]
[InlineData(Math.PI*3/4)]
[InlineData(Math.PI*1.99)]
[InlineData(999)]
[InlineData(-999)]
public void Ctg(double a) =>
Assert.Equal(1 / Math.Tan(a), Calculator.Calculate($"ctg({a})"), PRECISION);
[Theory]
[InlineData(0.9)]
[InlineData(1)]
[InlineData(-3)]
[InlineData(-2)]
public void Asin(double a) =>
Assert.Equal( Math.Asin(a), Calculator.Calculate($"asin({a})"), PRECISION);
[Theory]
[InlineData(0.9)]
[InlineData(1)]
[InlineData(-3)]
[InlineData(-2)]
public void Acos(double a) =>
Assert.Equal( Math.Acos(a), Calculator.Calculate($"acos({a})"), PRECISION);
[Theory]
[InlineData(0.9)]
[InlineData(1)]
[InlineData(-3)]
[InlineData(-2)]
public void Atan(double a) =>
Assert.Equal( Math.Atan(a), Calculator.Calculate($"atan({a})"), PRECISION);
[Theory]
[InlineData(0.9)]
[InlineData(1)]
[InlineData(-3)]
[InlineData(-2)]
public void Actg(double a) =>
Assert.Equal( Math.Atan(1 / a), Calculator.Calculate($"actg({a})"), PRECISION);
[Theory]
[InlineData(0.9)]
[InlineData(1)]
[InlineData(-3)]
[InlineData(-2)]
public void Ln(double a) =>
Assert.Equal( Math.Log(a), Calculator.Calculate($"ln({a})"), PRECISION);
}

View File

@ -0,0 +1,4 @@
global using System;
global using System.Globalization;
global using Xunit;
global using FusionCalculator;

View File

@ -0,0 +1,57 @@
namespace SharpCalculator.Tests;
public class OperatorTests
{
public OperatorTests()
{
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
}
[Theory]
[InlineData(15,5)]
[InlineData(13,-6)]
[InlineData(-1,-6)]
[InlineData(-13,6)]
public void Sum(double a,double b) =>
Assert.Equal(a+b, Calculator.Calculate($"({a})+({b})"));
[Theory]
[InlineData(15,5)]
[InlineData(13,-6)]
[InlineData(-1,-6)]
[InlineData(-13,6)]
public void Subtract(double a,double b) =>
Assert.Equal(a-b, Calculator.Calculate($"({a})-({b})"));
[Theory]
[InlineData(15,5)]
[InlineData(13,-6)]
[InlineData(-1,-6)]
[InlineData(-13,6)]
public void Multiplying(double a,double b) =>
Assert.Equal(a*b, Calculator.Calculate($"({a})*({b})"));
[Theory]
[InlineData(15,5)]
[InlineData(24,-6)]
[InlineData(-12,-6)]
[InlineData(-36,6)]
public void Dividing(double a,double b) =>
Assert.Equal(a/b, Calculator.Calculate($"({a})/({b})"));
[Theory]
[InlineData(2,5)]
[InlineData(1,-1)]
[InlineData(-3,-4)]
[InlineData(-2,2)]
public void Power(double a,double b) =>
Assert.Equal(Math.Pow(a,b), Calculator.Calculate($"({a})^({b})"));
[Theory]
[InlineData(5,2)]
[InlineData(1,-1)]
[InlineData(-3,-2)]
[InlineData(-2,2)]
public void Mod(double a,double b) =>
Assert.Equal( a%b, Calculator.Calculate($"({a})%({b})"));
}

View File

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.6.4" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FusionCalculator\FusionCalculator.csproj" />
</ItemGroup>
</Project>

View File

@ -11,6 +11,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solution_items", "solution_
README.md = README.md README.md = README.md
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpCalculator.Tests", "SharpCalculator.Tests\SharpCalculator.Tests.csproj", "{E929E48D-D11B-4FB5-AC6F-D0D50E2B3BD1}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -25,5 +27,9 @@ Global
{8EA39217-DEBD-493B-A19C-5505B58E03FA}.Debug|Any CPU.Build.0 = Debug|Any CPU {8EA39217-DEBD-493B-A19C-5505B58E03FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8EA39217-DEBD-493B-A19C-5505B58E03FA}.Release|Any CPU.ActiveCfg = Release|Any CPU {8EA39217-DEBD-493B-A19C-5505B58E03FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8EA39217-DEBD-493B-A19C-5505B58E03FA}.Release|Any CPU.Build.0 = Release|Any CPU {8EA39217-DEBD-493B-A19C-5505B58E03FA}.Release|Any CPU.Build.0 = Release|Any CPU
{E929E48D-D11B-4FB5-AC6F-D0D50E2B3BD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E929E48D-D11B-4FB5-AC6F-D0D50E2B3BD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E929E48D-D11B-4FB5-AC6F-D0D50E2B3BD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E929E48D-D11B-4FB5-AC6F-D0D50E2B3BD1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

BIN
uml/FusionCalculator.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 KiB

File diff suppressed because it is too large Load Diff