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; } } }