EduNetworkBuilder/EduNetworkBuilder/ActionClass.cs

347 lines
15 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
namespace EduNetworkBuilder
{
public class ActionCollection
{
Network StartingState = null;
public List<NetworkAction> NetActions = new List<NetworkAction>();
NetworkAction CurrentNetAction = null;
public bool HasUnsavedChanges = false;
public Network GetNet { get { return StartingState; } }
public int GetActionCount { get { if (CurrentNetAction == null) return 0; return CurrentNetAction.Actions.Count; } }
public void RegisterNet(Network starting)
{
StartingState = Network.DeepClone(starting);
CurrentNetAction = FindAction(starting);
if(CurrentNetAction == null)
CurrentNetAction = new NetworkAction(starting);
}
public NetworkAction GetCurrentNetAction()
{
return CurrentNetAction;
}
public void Add(ActionClass What)
{
if(CurrentNetAction == null || CurrentNetAction.HasBeenStored == true)
{
Network start = NB.GetNetwork();
if (start == null) return;//Do nothing
CurrentNetAction = new NetworkAction(start);
}
CurrentNetAction.HasBeenStored = false;// We have a change. That change has not been pushed
CurrentNetAction.Add(What);
}
public NetworkAction FindAction(Network Fitting)
{
return FindAction(NameFromNet(Fitting));
}
public NetworkAction FindAction(string Fitting)
{
foreach(NetworkAction one in NetActions)
{
if (one.NetworkName == Fitting)
return one;
}
return null;
}
public bool CurrentNeedsStoring
{ get {
if (CurrentNetAction == null) return false;
return (CurrentNetAction.HasBeenStored == false);
}
}
public ActionClass RunAction(int WhichIndex)
{
if (CurrentNetAction == null) return null;
if (WhichIndex < CurrentNetAction.Actions.Count)
{
CurrentNetAction.Actions[WhichIndex].DoAction();
return CurrentNetAction.Actions[WhichIndex];
}
return null;
}
/// <summary>
/// Take the current actionlist and save it to the stored actionlists.
/// We use this when we have successfully solved a network and want to store
/// this solution process
/// </summary>
public void PushActionToList()
{
//remove an old one if it exists
if (CurrentNetAction != null)
{
NetworkAction NA = GetActionlistFromName(CurrentNetAction.NetworkName);
if (NA != null) NetActions.Remove(NA);
}
//Add this one
CurrentNetAction.HasBeenStored = true; //Note that we have stored it
NetActions.Add(CurrentNetAction);
//Note that the long-term action list has some new actions which have not been saved
HasUnsavedChanges = true;
}
/// <summary>
/// Return true if we already have a solved state for this network
/// </summary>
/// <param name="starting"></param>
/// <returns></returns>
public bool AlreadyHaveNet(Network starting)
{
//Look up the network to see if we have it already
return AlreadyHaveNet(NameFromNet(starting));
}
public bool AlreadyHaveNet(string starting)
{
NetworkAction NA = GetActionlistFromName(starting);
if (NA != null) return true; //one exists
return false;
}
public NetworkAction GetActionlistFromNet(Network starting)
{
return GetActionlistFromName(NameFromNet(starting));
}
public NetworkAction GetActionlistFromName(string starting)
{
foreach (NetworkAction NA in NetActions)
{
if (NA.NetworkName == starting) return NA;
}
return null;
}
private string NameFromNet(Network theNet)
{
return theNet.PuzzleName;
}
}
public class NetworkAction
{
public string NetworkName = "";
public List<ActionClass> Actions = new List<ActionClass>();
/// <summary>
/// This tells us if it has been stored to the long-term action list.
/// </summary>
public bool HasBeenStored = false;
public bool HasPassed = false;
public bool HasFailed = false;
public NetworkAction() { }
public NetworkAction(string Name)
{
NetworkName = Name;
Actions.Clear();
}
public NetworkAction(Network Start)
{
if (Start == null)
Start = NB.GetNetwork();
if (Start != null)
NetworkName = Start.PuzzleName;
else
NetworkName = "Empty";
Actions.Clear();
}
public void Add(ActionClass What)
{
Actions.Add(What);
}
public void SetPassed()
{
HasPassed = true;
HasFailed = false;
}
public void SetFailed()
{
HasPassed = false;
HasFailed = true;
}
}
public class ActionClass
{
public NBAction Action = NBAction.none;
public int SourceID = -1; //used for basically everything
public NB_IPAddress Destination; //used for pinging, arp, traceroute
public HostNicID SourceNIC; //used for links
public HostNicID DestNic; //Used for links
public Point Location; //Used when making a new device or moving an old device
public NetworkComponentType newItemType = NetworkComponentType.none; //Making new device
public NetworkComponent ChangedComponent = null;
public void DoAction()
{
Network myNet = NB.GetNetwork();
NetworkDevice source = myNet.GetDeviceFromID(SourceID);
NetworkComponent sourceC = myNet.GetComponentFromID(SourceID);
NetworkLink sourceNL;
switch (Action)
{
case NBAction.changecomponent:
//This could be a link or a device we are changing.
if(ChangedComponent is NetworkDevice)
{
source.UpdateFromComponent(ChangedComponent); //Copy any changes across
source.SetImageFromType(); //The image was not saved. Re-make it
}
else
{ //It is a link. Delete the old, make the new. Mark as linked
if(source != null)
myNet.RemoveComponent(source);
sourceNL = (NetworkLink)ChangedComponent;
myNet.MarkAsLinked(sourceNL.Src, sourceNL.GetUniqueIdentifier);
myNet.MarkAsLinked(sourceNL.Dst, sourceNL.GetUniqueIdentifier);
myNet.AddItem(ChangedComponent);
}
if(NB.DebugActions) { Console.WriteLine("Changing a component: " + source.hostname); }
break;
case NBAction.changelocation:
if (source != null)
{
source.ChangeLocation(Location);
source.UnHide(); //In case it was hidden
if (NB.DebugActions) { Console.WriteLine("Changing location for: " + source + " " + Location.X + ":" +Location.Y); }
}
break;
case NBAction.deletecomponent:
//Deleting the item is easy, but we also need to delete any links to that item
List<HostNicID> NicIDs = new List<HostNicID>();
if (source != null)
{
if (myNet.ItemIsCritical(source.hostname))
return; //we cannot delete this
NicIDs = source.GetHostNicIDs();
foreach (HostNicID nicID in NicIDs)
{
myNet.RemoveLinksToNic(nicID);
}
myNet.RemoveComponent(source);
if (NB.DebugActions) { Console.WriteLine("Deleting a device: " + source.hostname); }
} else if(sourceC != null && sourceC is NetworkLink)
{
if (myNet.ItemIsCritical(sourceC.hostname))
return; //We cannot remove this link
NetworkLink SourceL = (NetworkLink)sourceC;
SourceL.Destroy(); //Mark both ends as being deleted
myNet.RemoveComponent(SourceL); //Get rid of this link
if (NB.DebugActions) { Console.WriteLine("Deleting a link: " + source.hostname); }
}
break;
case NBAction.newdevice:
bool CanDo = true;
Point tLoc = myNet.clickedPosCentered(Location);
Point CenteredLocation = new Point(Location.X - (Location.X - tLoc.X), Location.Y - ((Location.Y - tLoc.Y)));
Point TopLeft = Location;
Point TopRight = new Point(TopLeft.X + myNet.itemsize, TopLeft.Y);
Point BottomRight = new Point(TopLeft.X + myNet.itemsize, TopLeft.Y + myNet.itemsize);
Point BottomLeft = new Point(TopLeft.X, TopLeft.Y + myNet.itemsize);
ChangedComponent = null; //if we cannot place it, this = null for reference
if (myNet.BlockedByTree(Location)) CanDo = false;
if (myNet.BlockedByTree(TopLeft)) CanDo = false;
if (myNet.BlockedByTree(TopRight)) CanDo = false;
if (myNet.BlockedByTree(BottomRight)) CanDo = false;
if (myNet.BlockedByTree(BottomLeft)) CanDo = false;
if (CanDo)
{
ChangedComponent = (NetworkDevice)myNet.AddItem(newItemType, Location);
if (NB.DebugActions) { Console.WriteLine("Adding a Device: " + source.hostname); }
}
else
{
NB.SetBuilderWindowStatis(NB.Translate("NB_TreePlacementError"));
if (NB.DebugActions) { Console.WriteLine("Unable to add device: " + source.hostname); }
}
break;
case NBAction.dhcp:
if (source != null)
{
source.DHCPRequestFromHere();
if (NB.DebugActions) { Console.WriteLine("Requesting DHCP: " + source.hostname); }
}
break;
case NBAction.arp:
if (source != null)
{
source.AskArpFromHere(Destination);
if (NB.DebugActions) { Console.WriteLine("Requesting DHCP: " + source.hostname); }
}
break;
case NBAction.cleararp:
if (source != null)
{
source.ClearArps();
if (NB.DebugActions) { Console.WriteLine("Clearing ARP: " + source.hostname); }
}
break;
case NBAction.ping:
if (source != null)
{
source.PingFromHere(Destination);
if (NB.DebugActions) { Console.WriteLine("Pinging " + Destination.GetIPString + " from " + source.hostname); }
}
break;
case NBAction.traceroute:
if (source != null)
{
source.TracerouteFromHere(Destination);
if (NB.DebugActions) { Console.WriteLine("Traceroute: " + Destination.GetIPString + " from " + source.hostname); }
}
break;
case NBAction.replace:
if(sourceC is NetworkDevice)
{
source.ClearIPs(); //reset the device
source.IsBurned = false; //If it had been burned before, it is no longer burned
source.PowerOff = true;
source.BadSprayCount = 0;
//Mark the replace test as "done"
myNet.RegisterDeviceReset(source.hostname); //replacing something powers it off
myNet.RegisterDeviceReplaced(source.hostname); //replace it.
if (NB.DebugActions) { Console.WriteLine("Replacing device: " + source.hostname); }
}
else if (sourceC is NetworkLink)
{
sourceNL = (NetworkLink)sourceC;
if (sourceNL.theLinkType != LinkType.wireless)
{
HostNicID sourceID = sourceNL.Src;
HostNicID destID = sourceNL.Dst;
myNet.RemoveComponent(sourceNL);
NetworkLink nNL = new NetworkLink(sourceID, destID, LinkType.normal);
myNet.AddItem(nNL);
if (NB.DebugActions) { Console.WriteLine("Replacing link: " + source.hostname); }
}
}
break;
case NBAction.replaceUPS:
myNet.RegisterUPSAdded(source.hostname);
if (NB.DebugActions) { Console.WriteLine("Replacing UPS on: " + source.hostname); }
break;
case NBAction.poweroff:
source.PowerOff = true;
myNet.RegisterDeviceReset(source.hostname);
if (NB.DebugActions) { Console.WriteLine("Powering off: " + source.hostname); }
break;
case NBAction.poweron:
source.PowerOff = false;
if (NB.DebugActions) { Console.WriteLine("Powering on: " + source.hostname); }
//We might see about exploding the device here.
break;
}
}
}
}