using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
namespace M04
{
public partial class Form1 : Form
{
public Network net;
public Form1()
{
InitializeComponent();
}
// Vytvoří objektu ze XML, přidá všechny hradla do editačního boxu
private void bLoad_Click(object sender, EventArgs e)
{
net = CreateNetworkFromXML(this.tbNetwork.Text);
if (net == null) { return; }
editingGate = null;
this.panelEditace.Visible = false;
this.bKrok.Enabled = false;
NaloadujHradla();
this.pictureBox1.Invalidate();
this.pictureBox1.Update();
}
// Přidá všechna hradla do editačního boxu
private void NaloadujHradla()
{
this.cbHradla.Items.Clear();
for (int i = 0; i < net.Gates.Count; i++)
{
this.cbHradla.Items.Add(i.ToString() + ": " + net.Gates[i].Type + ", X" + net.Gates[i].X);
}
}
// Vytvoří objekty z XML dat
private Network CreateNetworkFromXML(string filename)
{
if (!System.IO.File.Exists(filename)) { MessageBox.Show("Vybraná síť neexistuje.", "Chyba", MessageBoxButtons.OK, MessageBoxIcon.Error); return null; }
net = new Network();
bool searchingGate = false;
this.textBox3.Text = System.IO.File.ReadAllText(filename);
XmlTextReader xmlr = new XmlTextReader(filename);
while (xmlr.Read())
{
if (!(xmlr.NodeType == XmlNodeType.EndElement))
{
if (xmlr.Name == "net") { Logg("Načítám hradlovou síť..."); }
if (xmlr.Name == "input")
{
if (!searchingGate)
{
Logg("Načítám vstup s ID " + xmlr.GetAttribute("id"));
net.Inputs.Add(new InputOutput(intize(xmlr.GetAttribute("x")),
intize(xmlr.GetAttribute("y")),
intize(xmlr.GetAttribute("w")),
intize(xmlr.GetAttribute("h")),
xmlr.GetAttribute("id")));
}
else
{
net.Gates[net.Gates.Count - 1].Inputs.Add(new ident(xmlr.GetAttribute("id"), -1));
}
}
if (xmlr.Name == "output")
{
if (!searchingGate)
{
Logg("Načítám výstup s ID " + xmlr.GetAttribute("id"));
net.Outputs.Add(new InputOutput(intize(xmlr.GetAttribute("x")),
intize(xmlr.GetAttribute("y")),
intize(xmlr.GetAttribute("w")),
intize(xmlr.GetAttribute("h")),
xmlr.GetAttribute("id")));
}
else
{
net.Gates[net.Gates.Count - 1].Outputs.Add(new ident(xmlr.GetAttribute("id"), -1));
}
}
if (xmlr.Name == "gate")
{
searchingGate = true;
net.Gates.Add(new Gate(xmlr.GetAttribute("type"), intize(xmlr.GetAttribute("x")),
intize(xmlr.GetAttribute("y")),
intize(xmlr.GetAttribute("w")),
intize(xmlr.GetAttribute("h"))));
Logg("Načítám bránu typu " + xmlr.GetAttribute("type"));
}
}
else
{
if (xmlr.Name == "gate")
{
searchingGate = false;
}
}
}
return net;
}
// Pomocná utilita - převede text na číslo se zabezpečením proti chybovému vstupu
private int intize(string text)
{
int outint = 0;
if (Int32.TryParse(text, out outint)) { return outint; } else { return 0; }
}
// Slouží k zaznamenávání průběhu akce (logging), výsledek vidíte v textboxu vpravo
private void Logg(string p)
{
if (!this.chNoLogging.Checked)
this.textBox4.Text += p + Environment.NewLine;
}
Font font = new Font(FontFamily.GenericSansSerif,10);
public float zoom = 3;
// Vykresluje a překresluje obrázek sítě
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (net != null)
{
e.Graphics.FillRectangle(Brushes.Gray, e.ClipRectangle);
foreach (InputOutput i in net.Inputs)
{
e.Graphics.DrawRectangle(Pens.Black, new Rectangle((int)(i.X * zoom), (int)(i.Y * zoom), (int)(i.Width * zoom), (int)(i.Height * zoom)));
Describe(e, i.X, i.Y, i.Width, i.Height, i.Value.ToString(), Brushes.White);
}
foreach (InputOutput i in net.Outputs)
{
e.Graphics.DrawRectangle(Pens.Black, new Rectangle((int)(i.X * zoom), (int)(i.Y * zoom), (int)(i.Width * zoom), (int)(i.Height * zoom)));
Describe(e, i.X, i.Y, i.Width, i.Height, i.Value.ToString(), Brushes.White);
}
foreach (Gate g in net.Gates)
{
// Žlutě se vykreslí ta hradla, která byla při posledním kroku změněna
Brush clr = Brushes.White;
Pen pen = Pens.Black;
if (g.JustChanged == true) { clr = Brushes.Yellow; pen = Pens.Yellow; }
e.Graphics.DrawRectangle(pen, new Rectangle((int)(g.X * zoom), (int)(g.Y * zoom), (int)(g.Width * zoom), (int)(g.Height * zoom)));
string ins = "";
foreach(ident i in g.Inputs)
{
if (i.Value == -1) { ins += "?"; } else { ins += i.Value.ToString(); }
// Draty
foreach (Gate g2 in net.Gates)
{
if (g != g2)
{
foreach(ident outer in g2.Outputs)
{
if (outer.Id == i.Id)
{
e.Graphics.DrawLine(Pens.Black, new PointF(g.X * zoom, g.Y * zoom), new PointF(g2.X * zoom + g2.Width * zoom, g2.Y * zoom + g2.Height * zoom));
break;
}
}
}
}
foreach(InputOutput inp in net.Inputs)
{
if (i.Id == inp.Id)
{
e.Graphics.DrawLine(Pens.Black, new PointF(g.X * zoom, g.Y * zoom), new PointF(inp.X * zoom + inp.Width * zoom, inp.Y * zoom + inp.Height * zoom));
}
}
}
foreach (ident o in g.Outputs)
{
foreach (InputOutput output in net.Outputs)
{
if (o.Id == output.Id)
{
e.Graphics.DrawLine(Pens.Black, new PointF(output.X * zoom, output.Y * zoom), new PointF(g.X * zoom + g.Width * zoom, g.Y * zoom + g.Height * zoom));
}
}
}
string ous = "?";
if (g.Outputs[0].Value != -1) { ous = g.Outputs[0].Value.ToString(); }
Describe(e, g.X, g.Y, g.Width, g.Height, ins, clr);
Describe(e, g.X, g.Y + g.Height, g.Width, g.Height+20,ous , clr);
}
}
}
// Pomocná utilita - vykreslí text nad vybrané hradlo/vstup/výstup
private void Describe(PaintEventArgs e, int x, int y, int w, int h, string display, Brush clr)
{
e.Graphics.DrawString(display, font, clr, new PointF(x*zoom + w*zoom / 2 - 7, y*zoom - 20));
}
// Pomocná utilita - OpenFileDialog
private void bOpenHradlo_Click(object sender, EventArgs e)
{
this.openFileDialog1.Title = "Načíst hradlovou síť...";
if (this.openFileDialog1.ShowDialog() == DialogResult.OK)
{
this.tbNetwork.Text = this.openFileDialog1.FileName;
}
}
// Pomocná utilita - OpenFileDialog
private void bOpenData_Click(object sender, EventArgs e)
{
this.openFileDialog1.Title = "Načíst soubor se vstupy...";
if (this.openFileDialog1.ShowDialog() == DialogResult.OK)
{
this.tbData.Text = this.openFileDialog1.FileName;
}
}
// Provede jeden krok v simulaci tímto způsobem:
// ----
// Projde všechna hradla a pro každé hradlo projde všemi jinými hradly, zda náhodou nemají takový výstup,
// jaké toto hradlo má vstup. V takovém případě tento výstup po "drátu" přejde na vstup.
// Poté, pokud už má hradlo všechny vstupy, provede danou operaci nebo, v případě vnořené sítě,
// spustí simulaci podsítě.
public void PerformStep(Network worknet)
{
Logg("Provádím krok...");
foreach (Gate g in worknet.Gates)
{
g.JustChanged = false;
// Plnění vstupů hradel
foreach (ident i in g.Inputs)
{
foreach (InputOutput start in worknet.Inputs)
{
if (start.Id == i.Id && i.Value == -1) { g.JustChanged = true; i.Value = start.Value; Logg("Hradlo " + g.Type + " ma nyni na vstupu " + i.Id + " hodnotu " + i.Value.ToString()); }
}
foreach (Gate outg in worknet.Gates)
{
if (g != outg)
{
foreach (ident outout in outg.Outputs)
{
if (outout.Id == i.Id && outout.Value != -1 && i.Value == -1)
{
i.Value = outout.Value;
g.JustChanged = true;
Logg("Hradlo " + g.Type + " má nyní na vstupu " + i.Id + " hodnotu " + i.Value.ToString());
}
}
}
}
}
// Plneni vystupu
foreach (ident output in g.Outputs)
{
foreach (InputOutput cil in worknet.Outputs)
{
if (output.Id == cil.Id && output.Value != -1)
{
cil.Value = output.Value;
Logg("Výstup " + cil.Id + " má hodnotu " + cil.Value);
}
}
}
}
foreach(Gate g in worknet.Gates)
{
// Vyhodnocování hradel
bool allset = true;
foreach (ident i in g.Inputs) { if (i.Value == -1) { allset = false; } }
if (g.Outputs[0].Value != -1) { allset = false; }
int resulting = -1;
if (allset)
{
switch (g.Type)
{
case "AND": resulting = 1; foreach (ident i in g.Inputs) { if (i.Value == 0) { resulting = 0; break; } } break;
case "OR": resulting = 0; foreach (ident i in g.Inputs) { if (i.Value == 1) { resulting = 1; break; } } break;
case "XOR": resulting = 0; foreach (ident i in g.Inputs) { if (i.Value == 1) { if (resulting == 1) { resulting = 0; } else { resulting = 1; } } } break;
case "NOT": if (g.Inputs[0].Value == 1) { resulting = 0; } else { resulting = 1; } break;
}
if (resulting != -1)
{
Logg("Hradlo " + g.Type + " má nyní na výstupu " + resulting.ToString());
g.Outputs[0].Value = resulting;
}
else
{
string needname = System.IO.Path.GetDirectoryName(this.tbNetwork.Text) + "\\" + g.Type;
//MessageBox.Show(needname);
Network subnet = CreateNetworkFromXML(needname); string inputrow = "";
foreach(ident i in g.Inputs) { inputrow += i.Value.ToString(); }
string restext;
SolveNetwork(subnet, inputrow, out restext);
foreach (InputOutput cil in subnet.Outputs)
{
foreach (ident o in g.Outputs)
{
if (o.Id == cil.Id) { o.Value = cil.Value; break; }
}
}
Logg("Hradlo " + g.Type + " má nyní nastavené výstupní hodnoty.");
}
}
}
if (chKrokovat.Checked)
{
this.pictureBox1.Invalidate();
this.pictureBox1.Update();
}
}
// Spustí vlastní simulaci
// Nejprve rozhodne na základě vstupních dat, zda se bude krokovat, nebo zda bude celá simulace
// probíhat najednou.
private void button2_Click(object sender, EventArgs e)
{
if (!System.IO.File.Exists(this.tbData.Text)) { MessageBox.Show("Vybraný soubor neexistuje.", "Chyba", MessageBoxButtons.OK, MessageBoxIcon.Error); return; }
if (net == null) { MessageBox.Show("Nejprve vyberte síť.", "Chyba", MessageBoxButtons.OK, MessageBoxIcon.Error); return; }
this.textBox4.Clear();
this.bKrok.Enabled = true;
Logg("*****************************");
string[] lines = System.IO.File.ReadAllLines(this.tbData.Text);
// Nacist prvni radek
if (lines.Length > 1)
{
if (this.chKrokovat.Checked == false)
{
string resultingtext = "";
foreach (string radka in lines)
{
string result;
// Reset All Data in Network
foreach (Gate g in net.Gates)
{
foreach (ident input in g.Inputs) { input.Value = -1; }
foreach (ident output in g.Outputs) { output.Value = -1; }
}
foreach (InputOutput cil in net.Outputs)
{
cil.Value = -1;
}
SolveNetwork(net, radka, out result);
resultingtext += result + Environment.NewLine;
}
System.Console.Write(resultingtext);
MessageBox.Show(resultingtext, "Odesláno na standartní výstup");
return;
}
}
else { this.chKrokovat.Checked = true; }
string row = lines[0];
for (int i = 0; i < row.Length; i++)
{
net.Inputs[i].Value = intize(row[i].ToString());
Logg("Vstup " + i.ToString() + " je nyní " + net.Inputs[i].Value.ToString());
}
Logg("");
Logg("Nyní můžete krokovat.");
Logg("");
this.bKrok.Enabled = true;
}
// Provádí jednotlivé kroky dokud nemají všechny výstupy skutečnou hodnotu (ne -1)
private void SolveNetwork(Network worknet, string row, out string result)
{
// Inputs
for (int i = 0; i < row.Length; i++)
{
worknet.Inputs[i].Value = intize(row[i].ToString());
Logg("Vstup " + i.ToString() + " je nyni " + net.Inputs[i].Value.ToString());
}
bool allset = false;
while (!allset)
{
PerformStep(worknet);
allset = true;
foreach (InputOutput output in worknet.Outputs)
{
if (output.Value == -1) { allset = false; }
}
}
result = "";
foreach (InputOutput output in worknet.Outputs)
{
result += output.Value.ToString();
}
}
// Pomocná utilita
private void bKrok_Click(object sender, EventArgs e)
{
PerformStep(net);
CheckFinishing();
}
// Animace = okno celoobrazovkového režimu
// Tato funkce nejprve přemístí PictureBox do nového okna a pak toto okno spustí.
private void button1_Click(object sender, EventArgs e)
{
Animace animace = new Animace();
this.pictureBox1.Parent = animace;
this.pictureBox1.Left = 2;
this.pictureBox1.Top = 25;
this.pictureBox1.Width = 1270;
this.pictureBox1.Height = 1000;
animace.Owner = this;
animace.ShowDialog(this);
}
// Zoom
public void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == '+') { zoom += 0.5f; }
if (e.KeyChar == '-') { zoom -= 0.5f; }
this.pictureBox1.Invalidate();
this.pictureBox1.Update();
}
// Během krokování tato funkce zjišťuje, zda by již nemělo krokování skončit
public void CheckFinishing()
{
bool allset = true;
string resultats = "";
foreach (InputOutput o in net.Outputs)
{
if (o.Value == -1) { allset = false; }
resultats += o.Id + " = " + o.Value + "\n";
}
if (allset)
{
MessageBox.Show("Právě jste udělali poslední krok a na výstupu již jsou správné hodnoty:\n\n" + resultats, "Simulace dokončena");
}
}
// Tu nápovědu si fakt přečíst musíte...
private void Form1_Load(object sender, EventArgs e)
{
NapovedaForm napoveda = new NapovedaForm();
napoveda.ShowDialog(this);
}
// To kdybste si ji zapomněli přečíst napoprvé...
private void button3_Click(object sender, EventArgs e)
{
NapovedaForm napoveda = new NapovedaForm();
napoveda.ShowDialog();
}
// Pomocná utilita - SaveFileDialog
private void button5_Click(object sender, EventArgs e)
{
if (this.saveFileDialog1.ShowDialog() == DialogResult.OK)
{
this.tbSaveTo.Text = this.saveFileDialog1.FileName;
}
}
// Převede aktuální objekty sítě pomocí skládání řetězců na XML
private void button4_Click(object sender, EventArgs e)
{
string output = "" + Environment.NewLine;
foreach (InputOutput input in net.Inputs)
{
output += "" + Environment.NewLine;
}
foreach (Gate g in net.Gates)
{
output += "" + Environment.NewLine;
foreach (ident i in g.Inputs)
{
output += "" + Environment.NewLine;
} foreach (ident i in g.Outputs)
{
output += "" + Environment.NewLine;
}
output += "" + Environment.NewLine;
}
foreach (InputOutput outer in net.Outputs)
{
output += "" + Environment.NewLine;
}
output += "";
System.IO.File.WriteAllText(this.tbSaveTo.Text, output);
}
// Této funkci nevěnujte pozornost, ale pokud jste došli až sem, můžete ji považovat za Easter Egg.
// (Placeholder - zde bude obsah easter eggu)
private void pictureBox1_Click(object sender, EventArgs e)
{
}
// Pomocná utilita - uživatel zde vybere hradlo k editaci nebo stiskne myši a vytvoří hradlo nové
public Gate editingGate = null;
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (net != null)
{
int realx = (int)(e.X / zoom);
int realy = (int)(e.Y / zoom);
bool clickedright = false;
foreach (Gate g in net.Gates)
{
if ((realx > g.X) && (realx < g.X + g.Width) && (realy > g.Y) && (realy < g.Y + g.Height))
{
editingGate = g;
this.panelEditace.Visible = true;
this.nX.Value = g.X;
nY.Value = g.Y; nW.Value = g.Width; nH.Value = g.Height;
cbType.Text = g.Type;
clickedright = true;
}
}
if (!clickedright && this.chCreatingMode.Checked)
{
if (MessageBox.Show("Chcete zde vytvořit nové hradlo?", "Vytvořit hradlo?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
net.Gates.Add(new Gate("AND", realx, realy, 20, 10));
net.Gates[net.Gates.Count - 1].Outputs = new List();
net.Gates[net.Gates.Count - 1].Outputs.Add(new ident("NONEXISTENT", -1));
Gate g = net.Gates[net.Gates.Count - 1];
this.panelEditace.Visible = true;
this.nX.Value = g.X;
nY.Value = g.Y; nW.Value = g.Width; nH.Value = g.Height;
cbType.Text = g.Type;
NaloadujHradla();
this.pictureBox1.Invalidate();
this.pictureBox1.Update();
}
this.chCreatingMode.Checked = false;
}
}
}
// Načte data hradla vybraného v editačním boxu (ne na obrázku)
private void button7_Click(object sender, EventArgs e)
{
Gate g = null;
int whatgate = this.cbHradla.SelectedIndex;
g = net.Gates[whatgate];
editingGate = g;
this.panelEditace.Visible = true;
this.nX.Value = g.X;
nY.Value = g.Y; nW.Value = g.Width; nH.Value = g.Height;
cbType.Text = g.Type;
}
// Uloží změněná data
private void button6_Click(object sender, EventArgs e)
{
editingGate.X = (int)nX.Value;
editingGate.Y = (int)nY.Value;
editingGate.Width = (int)nW.Value;
editingGate.Height = (int)nH.Value;
editingGate.Type = cbType.Text;
this.pictureBox1.Invalidate();
this.pictureBox1.Update();
}
}
// Ehm... to je síť
public class Network
{
public List Gates = new List();
public List Inputs = new List();
public List Outputs = new List();
}
// Tohle je hradlo
public class Gate
{
public string Type = "";
public int X, Y, Width, Height;
public List Inputs = new List();
public List Outputs = new List();
public bool JustChanged = false;
public Gate(string type, int x, int y, int w, int h)
{
Type = type.ToUpper();
X = x;
Y = y;
Width = w;
Height = h;
}
}
// A tohle vstup nebo výstup
public class InputOutput
{
public int Y, X, Width, Height;
public string Id;
public int Value = -1;
public InputOutput(int x, int y, int w, int h, string id)
{
X = x; Y = y; Width = w; Height = h;
Id = id;
}
}
// A nakonec, toto je vstup nebo výstup hradla.
// Děkuji za dočtení až do konce.
public class ident
{
public string Id;
public int Value;
public ident(string id, int val)
{
Id = id;
Value = val;
}
}
}