[4sem] isaip01 done

This commit is contained in:
Andrew Nuark G 2021-02-13 02:22:31 +07:00
parent 494525d878
commit 6d9a79be20
12 changed files with 410 additions and 0 deletions

View file

@ -0,0 +1,8 @@
.idea/
.vscode/
.vs/
bin/
obj/
*.user

View file

@ -0,0 +1,12 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PlayfairCypher"
x:Class="PlayfairCypher.App">
<Application.DataTemplates>
<local:ViewLocator/>
</Application.DataTemplates>
<Application.Styles>
<FluentTheme Mode="Light"/>
</Application.Styles>
</Application>

View file

@ -0,0 +1,29 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using PlayfairCypher.ViewModels;
using PlayfairCypher.Views;
namespace PlayfairCypher
{
public class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow
{
DataContext = new MainWindowViewModel(),
};
}
base.OnFrameworkInitializationCompleted();
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

View file

@ -0,0 +1,161 @@
// ReSharper disable StringLiteralTypo
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PlayfairCypher.Models {
public class PlayfairCrypto {
private static readonly HashSet<char> EnAlphabet = new("ABCDEFGHIKLMNOPQRSTUVWXYZ");
public string Encrypt(string keyword, string text) {
var keyTable = GenerateTable(keyword);
var pairs = FormPairs(text);
var data = new StringBuilder(32);
foreach (var pair in pairs) {
var idx1 = FindCharIndex(ref keyTable, pair[0]);
var idx2 = FindCharIndex(ref keyTable, pair[1]);
var x1 = idx1 / 5; // x for rows
var y1 = idx1 % 5; // and y for cols
var x2 = idx2 / 5;
var y2 = idx2 % 5;
char c1, c2;
if (y1 == y2) {
c1 = keyTable[WrapIndex(x1 + 1), y1];
c2 = keyTable[WrapIndex(x2 + 1), y1];
}
else if (x1 == x2) {
c1 = keyTable[x1, WrapIndex(y1 + 1)];
c2 = keyTable[x1, WrapIndex(y2 + 1)];
}
else {
c1 = keyTable[x1, y2];
c2 = keyTable[x2, y1];
}
data.Append(c1).Append(c2);
}
return data.ToString();
}
public string Decrypt(string keyword, string text) {
var keyTable = GenerateTable(keyword);
var pairs = FormPairs(text);
var data = new StringBuilder(32);
foreach (var pair in pairs) {
var idx1 = FindCharIndex(ref keyTable, pair[0]);
var idx2 = FindCharIndex(ref keyTable, pair[1]);
var x1 = idx1 / 5; // x for rows
var y1 = idx1 % 5; // and y for cols
var x2 = idx2 / 5;
var y2 = idx2 % 5;
char c1, c2;
if (y1 == y2) {
c1 = keyTable[WrapIndex(x1 - 1), y1];
c2 = keyTable[WrapIndex(x2 - 1), y1];
}
else if (x1 == x2) {
c1 = keyTable[x1, WrapIndex(y1 - 1)];
c2 = keyTable[x1, WrapIndex(y2 - 1)];
}
else {
c1 = keyTable[x1, y2];
c2 = keyTable[x2, y1];
}
data.Append(c1).Append(c2);
}
return data.ToString();
}
private char[,] GenerateTable(string keyword) {
char[,] table = new char[5,5];
keyword = ClearKeyword(keyword);
for (var i = 0; i < keyword.Length; i++) {
table[i / 5,i % 5] = keyword[i];
}
var kwcSet = new HashSet<char>(keyword);
var autoAlphabet = EnAlphabet.Except(kwcSet).ToList();
for (var i = keyword.Length; i < 25; i++) {
table[i / 5,i % 5] = autoAlphabet[i-keyword.Length];
}
return table;
}
private static string ClearKeyword(string keyword) {
string data = "";
keyword = keyword.Replace("J", "I");
foreach (var kwc in keyword) {
if (!EnAlphabet.Contains(kwc) || kwc == ' ' || data.Contains(kwc)) {
continue;
}
data += kwc;
}
return data;
}
private static int FindCharIndex(ref char[,] table, char c) {
for (var i = 0; i < 25; i++) {
if (table[i / 5, i % 5] == c) {
return i;
}
}
throw new ArgumentOutOfRangeException($"Character '{c}' not fount in table");
}
private static List<string> FormPairs(string text) {
List<string> data = new ();
text = text.Replace("J", "I");
var cc = text[0];
for (var i = 1; i < text.Length; i++) {
if (cc != '\0' && !EnAlphabet.Contains(cc)) {
cc = '\0';
}
if (cc == '\0') {
cc = text[i];
}
else if (cc == text[i]) {
data.Add("" + cc + "X");
cc = text[i];
}
else {
data.Add("" + cc + text[i]);
cc = '\0';
}
}
if (cc != '\0') {
data.Add("" + cc + "X");
}
return data;
}
private static int WrapIndex(int idx) {
if (idx < 0) {
idx += 5;
}
return idx % 5;
}
}
}

View file

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Folder Include="Models\" />
<AvaloniaResource Include="Assets\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.10.0" />
<PackageReference Include="Avalonia.Desktop" Version="0.10.0" />
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.0" />
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.0" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,16 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlayfairCypher", "PlayfairCypher.csproj", "{5AAEBCD9-0ADD-4C76-B1B4-92569D82970B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5AAEBCD9-0ADD-4C76-B1B4-92569D82970B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5AAEBCD9-0ADD-4C76-B1B4-92569D82970B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5AAEBCD9-0ADD-4C76-B1B4-92569D82970B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5AAEBCD9-0ADD-4C76-B1B4-92569D82970B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,14 @@
using Avalonia;
using Avalonia.ReactiveUI;
namespace PlayfairCypher {
internal static class Program {
public static void Main(string[] args) {
BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
}
private static AppBuilder BuildAvaloniaApp() {
return AppBuilder.Configure<App>().UsePlatformDetect().LogToTrace().UseReactiveUI();
}
}
}

View file

@ -0,0 +1,33 @@
using System;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using PlayfairCypher.ViewModels;
using ReactiveUI;
namespace PlayfairCypher
{
public class ViewLocator : IDataTemplate
{
public bool SupportsRecycling => false;
public IControl Build(object data)
{
var name = data.GetType().FullName!.Replace("ViewModel", "View");
var type = Type.GetType(name);
if (type != null)
{
return (Control) Activator.CreateInstance(type)!;
}
else
{
return new TextBlock {Text = "Not Found: " + name};
}
}
public bool Match(object data)
{
return data is ReactiveObject;
}
}
}

View file

@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Reactive.Disposables;
using System.Text;
using Avalonia.Controls;
using PlayfairCypher.Models;
using ReactiveUI;
namespace PlayfairCypher.ViewModels {
public class MainWindowViewModel : ReactiveObject {
private string _keyword = "";
private string _inputText = "";
private string _outputText = "";
private bool _isEncrypting = true;
private readonly PlayfairCrypto _cryptor;
public MainWindowViewModel() {
_cryptor = new PlayfairCrypto();
}
public string Keyword {
get => _keyword;
set {
this.RaiseAndSetIfChanged(ref _keyword, value.ToUpper());
CalculateCypher();
}
}
public string InputText {
get => _inputText;
set {
this.RaiseAndSetIfChanged(ref _inputText, value.ToUpper());
CalculateCypher();
}
}
public string OutputText {
get => _outputText;
set => this.RaiseAndSetIfChanged(ref _outputText, value.ToUpper());
}
public bool IsEncrypting {
get => _isEncrypting;
set {
this.RaiseAndSetIfChanged(ref _isEncrypting, value);
InputText = OutputText;
}
}
public void ClearForm() {
InputText = "";
Keyword = "";
}
void CalculateCypher() {
if (InputText.Length == 0) {
OutputText = "";
return;
}
if (Keyword.Length == 0) {
OutputText = "Error: Keyword is empty";
return;
}
OutputText = IsEncrypting? _cryptor.Encrypt(Keyword.Trim(), InputText.Trim()) : _cryptor.Decrypt(Keyword.Trim(), InputText.Trim());
}
}
}

View file

@ -0,0 +1,33 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:PlayfairCypher.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
Width="700" Height="300"
x:Class="PlayfairCypher.Views.MainWindow"
Icon="/Assets/avalonia-logo.ico"
Title="PlayfairCypher">
<Design.DataContext>
<vm:MainWindowViewModel/>
</Design.DataContext>
<Grid RowDefinitions="Auto,20,*" Margin="20">
<Grid Grid.Row="0" ColumnDefinitions="*,40,Auto,Auto,Auto">
<TextBox Grid.Column="0" AcceptsReturn="True" ScrollViewer.VerticalScrollBarVisibility="Auto" Watermark="Keyword" NewLine=""
Text="{Binding Keyword}"/>
<CheckBox Grid.Column="2" Content="Encrypting" IsChecked="{Binding IsEncrypting}" />
<Button Grid.Column="4" Content="Clear form" Command="{Binding ClearForm}" />
</Grid>
<Grid Grid.Row="2" ColumnDefinitions="*,Auto,*">
<TextBox Grid.Column="0" AcceptsReturn="True" ScrollViewer.VerticalScrollBarVisibility="Auto"
Watermark="INPUT" UseFloatingWatermark="True" TextWrapping="Wrap"
Text="{Binding InputText}"/>
<GridSplitter Grid.Column="1" />
<TextBox Grid.Column="2" ScrollViewer.VerticalScrollBarVisibility="Auto" IsReadOnly="True"
Watermark="OUTPUT" UseFloatingWatermark="True" TextWrapping="Wrap"
Text="{Binding OutputText}"/>
</Grid>
</Grid>
</Window>

View file

@ -0,0 +1,18 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace PlayfairCypher.Views {
public class MainWindow : Window {
public MainWindow() {
InitializeComponent();
#if DEBUG
this.AttachDevTools();
#endif
}
private void InitializeComponent() {
AvaloniaXamlLoader.Load(this);
}
}
}