using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Xml.Linq;
using System.Windows;
namespace HradlovaSit
{
///
/// abstraktni trida, kterou dedi vsechny komponenty site vcetne site samotne
///
public abstract class BaseComponent
{
public BaseComponent()
{
Inputs = new Dictionary();
Outputs = new Dictionary();
}
///
/// vyhodnoti data na komponente
///
///
public abstract bool Evaluate();
///
/// vstupy komponenty
///
public virtual Dictionary Inputs { get; set; }
///
/// vystupy komponenty
///
public virtual Dictionary Outputs { get; set; }
public abstract Drawing Draw();//TODO...
///
/// nacte komponentu z XML elementu
///
public abstract bool LoadFromXML(XElement elem);
public abstract XElement SaveToXML();//TODO...
public virtual Rect Bounds { get; set; }
public virtual Net BaseNet { get; set; }
///
/// kolik vstupu ma jiz prirazenou hodnotu
///
public virtual int InputsSet { get; set; }
///
/// nacte z atributu elementu rozmery a pozici
///
///
///
protected bool LoadBounds(XElement elem)
{
foreach (var a in elem.Attributes())
{
string n = a.Name.LocalName.ToLower();
if (n == "x")
{
int v;
if (!int.TryParse(a.Value, out v)) return false;
this.Bounds = new Rect(v, this.Bounds.Y, this.Bounds.Width, this.Bounds.Height);
}
else if (n == "y")
{
int v;
if (!int.TryParse(a.Value, out v)) return false;
this.Bounds = new Rect(this.Bounds.X, v, this.Bounds.Width, this.Bounds.Height);
}
else if (n == "w")
{
int v;
if (!int.TryParse(a.Value, out v)) return false;
this.Bounds = new Rect(this.Bounds.X, this.Bounds.Y, v, this.Bounds.Height);
}
else if (n == "h")
{
int v;
if (!int.TryParse(a.Value, out v)) return false;
this.Bounds = new Rect(this.Bounds.X, this.Bounds.Y, this.Bounds.Width, v);
}
}
return true;
}
}
///
/// reprezentuje celou sit
///
public class Net : BaseComponent
{
public Dictionary Components = new Dictionary();
public List AllInputs = new List(), AllOutputs = new List();
///
/// Jednotlive hodnoty komponent podle ID
///
//public Dictionary ValuesDictionary = new Dictionary();
private List inputsOrder = new List(), outputsOrder = new List();
///
/// nacte vstupy site z retezce ve spravnem poradi
///
///
///
public bool InsertInputs(string inputs)
{
for (int i = 0; i < inputsOrder.Count; i++)
{
if (i >= inputs.Length) return false;
bool v = true;
if (inputs[i] == '0') v = false;
else if (inputs[i] != '1') return false;
this.Inputs[inputsOrder[i]] = v;
var c = from b in this.Components.Values where b is Input && b.Outputs.ContainsKey(inputsOrder[i]) select b;
if (c.Count() > 0) c.First().Outputs[inputsOrder[i]] = v;
}
return true;
}
///
/// vypise vystupy site ve spravnem poradi
///
///
public string OutputsToString()
{
string line = "";
for (int i = 0; i < outputsOrder.Count; i++)
{
var c = from b in this.Components.Values where b is Output && b.Inputs.ContainsKey(outputsOrder[i]) select b;
if (c.Count() > 0)
{
bool v = c.First().Inputs[outputsOrder[i]];
//bool v = this.Outputs[outputsOrder[i]];
if (v) line += "1";
else line += "0";
}
}
return line;
}
public override bool Evaluate()
{
foreach (var cmp in this.Components.Values)
{
cmp.InputsSet = 0;
}
Queue q = new Queue(this.inputsOrder);
while (q.Count > 0)
{
var i = q.Dequeue();
var c = from b in this.Components.Values where b.Inputs.ContainsKey(i) || b.Inputs.ContainsKey("out+" + i) select b;
var o1 = (from b in this.Components.Values where b.Outputs.ContainsKey(i) select b);
if (c.Count() == 0 || o1.Count() == 0) continue;
var o = o1.First().Outputs[i];
foreach (var a in c)
{
string inp = i;
if (!a.Inputs.ContainsKey(i)) inp = "out+" + i;
a.Inputs[inp] = o;
a.InputsSet++;
if (a.InputsSet == a.Inputs.Count)
{
if (!(a is Net))
{
if (a.Evaluate())
{
foreach (var output in a.Outputs.Keys)
{
q.Enqueue(output);
}
}
else return false;
}
}
}
}
return true;
}
public override Drawing Draw()
{
throw new NotImplementedException();
}
public override bool LoadFromXML(XElement elem)
{
this.Components.Add("net", this);
foreach (var e in elem.Elements())
{
string n = e.Name.LocalName.ToLower();
if (n == "input")
{
XAttribute idE = e.Attribute(XName.Get("id"));
if (idE == null) return false;
string id = idE.Value.ToLower();
if (this.Components.ContainsKey(id)) return false;
this.inputsOrder.Add(id);
if (!this.Inputs.ContainsKey(id))
this.Inputs.Add(id, false);
Input i = new Input();
if (!i.LoadFromXML(e)) return false;
this.Components.Add(id, i);
if (!this.AllOutputs.Contains(id))
this.AllOutputs.Add(id);
if (!i.Outputs.ContainsKey(id))
i.Outputs.Add(id, false);
}
else if (n == "output")
{
XAttribute idE = e.Attribute(XName.Get("id"));
if (idE == null) return false;
string id = "out+" + idE.Value.ToLower();
if (this.Components.ContainsKey(id)) return false;
this.outputsOrder.Add(id);
if (!this.Outputs.ContainsKey(id))
this.Outputs.Add(id, false);
Output o = new Output();
if (!o.LoadFromXML(e)) return false;
this.Components.Add(id, o);
//this.AllInputs.Add(id);
if (!o.Inputs.ContainsKey(id))
o.Inputs.Add(id, false);
}
else if (n == "gate")
{
XAttribute atr = e.Attribute(XName.Get("type"));
if (atr == null) return false;
string type = atr.Value.ToLower();
if (type == "and" || type == "or" || type == "not" || type == "xor")
{
Gate g = new Gate(this);
if (!g.LoadFromXML(e)) return false;
string id = g.Outputs.Keys.First();
if (this.Components.ContainsKey(id)) return false;
this.Components.Add(id, g);
}
else
{
try
{
XDocument doc = XDocument.Load(type);
var ele = (from c in doc.Descendants()
where c.NodeType == System.Xml.XmlNodeType.Element && c.Name.LocalName.ToLower() == "net"
select c).First();
Net net = new Net();
if (!net.LoadFromXML(ele)) return false;
if (this.Components.ContainsKey(type)) return false;
this.Components.Add(type, net);
}
catch (Exception)
{
MessageBox.Show("Nepodařilo se otevřít soubor.", "Chyba", MessageBoxButton.OK, MessageBoxImage.Error);
return false;
}
}
}
else { return false; }
}
return true;
}
public override XElement SaveToXML()
{
throw new NotImplementedException();
}
}
public enum GateType
{
And, Or, Xor, Not
}
public class Gate : BaseComponent
{
public Gate(Net baseNet)
: base()
{
BaseNet = baseNet;
}
GateType Type { get; set; }
public override bool Evaluate()
{
var b = false;
switch (Type)
{
case GateType.And:
b = true;
foreach (var i in this.Inputs.Values)
{
b = b && i;
}
break;
case GateType.Or:
foreach (var i in this.Inputs.Values)
{
b = b || i;
}
break;
case GateType.Xor:
int trues = 0;
foreach (var i in this.Inputs.Values)
{
if (i) trues++;
}
if (trues % 2 == 1) b = true;
break;
case GateType.Not:
b = !this.Inputs.Values.First();
break;
default:
break;
}
this.Outputs[this.Outputs.Keys.First()] = b;
return true;
}
public override Drawing Draw()
{
throw new NotImplementedException();
}
public override bool LoadFromXML(XElement elem)
{
XAttribute atr = elem.Attribute(XName.Get("type"));
if (atr == null) return false;
string type = atr.Value.ToLower();
if (type == "and") Type = GateType.And;
else if (type == "or") Type = GateType.Or;
else if (type == "xor") Type = GateType.Xor;
else if (type == "not") Type = GateType.Not;
else return false;
foreach (var e in elem.Descendants())
{
string n = e.Name.LocalName.ToLower();
if (n == "input")
{
if (this.Inputs.Count > 0 && Type == GateType.Not) return false;
XAttribute idE = e.Attribute(XName.Get("id"));
if (idE == null) return false;
string id = idE.Value.ToLower();
//if (this.BaseNet.AllInputs.Contains(id)) return false;
//this.BaseNet.AllInputs.Add(id);
if (!this.Inputs.ContainsKey(id))
this.Inputs.Add(id, false);
}
else if (n == "output")
{
if (this.Outputs.Count > 0) return false;
XAttribute idE = e.Attribute(XName.Get("id"));
if (idE == null) return false;
string id = idE.Value.ToLower();
if (this.BaseNet.AllOutputs.Contains(id)) return false;
this.BaseNet.AllOutputs.Add(id);
if (!this.Outputs.ContainsKey(id))
this.Outputs.Add(id, false);
}
else return false;
}
return this.LoadBounds(elem) && this.Inputs.Count > 0 && this.Outputs.Count == 1;
}
public override XElement SaveToXML()
{
throw new NotImplementedException();
}
}
public class Input : BaseComponent
{
public override bool Evaluate()
{
return true;
}
public override Drawing Draw()
{
throw new NotImplementedException();
}
public override bool LoadFromXML(XElement elem)
{
return this.LoadBounds(elem);
}
public override XElement SaveToXML()
{
throw new NotImplementedException();
}
}
public class Output : BaseComponent
{
public override bool Evaluate()
{
return true;
}
public override Drawing Draw()
{
throw new NotImplementedException();
}
public override bool LoadFromXML(XElement elem)
{
return this.LoadBounds(elem);
}
public override XElement SaveToXML()
{
throw new NotImplementedException();
}
}
}