From e6cffd5feb433bc8df7e2b50802dcde34680fa55 Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Wed, 8 Jul 2020 13:38:07 -0600 Subject: [PATCH 01/22] Push before changes. At this point, this does not work. DO NOT MERGE WITH MASTER - LR-WPAN netdevices and SixLowPan being installed on required nodes - TCP/UDP server/clients now using ipv6 and ipv4 addresses - PROBLEM: No communication between server and clients at this point. Changing the way LR-WPAN netdevices and SixLowPan are installed to see if that fixes anything. --- .gitignore | 9 +- NS3Mosaik/Makefile | 6 +- NS3Mosaik/NS3MosaikSim | Bin 1903400 -> 1928976 bytes NS3Mosaik/mosaik_api/include/NS3Netsim.h | 19 +- NS3Mosaik/mosaik_api/include/ns3-helper.h | 9 + NS3Mosaik/mosaik_api/src/NS3Netsim.cpp | 325 +++++++++++------- NS3Mosaik/mosaik_api/src/ns3-helper.cpp | 9 + .../include/multi-client-tcp-server-helper.h | 20 +- .../include/multi-client-tcp-server.h | 64 ++-- .../include/tcp-client-helper.h | 6 +- .../include/tcp-client.h | 8 +- .../src/multi-client-tcp-server-helper.cc | 3 +- .../src/multi-client-tcp-server.cc | 128 ++++--- .../tcp-server-and-client/src/tcp-client.cc | 32 +- .../tcp-server-and-client/test/tcp-tester.cc | 172 --------- .../include/custom-udp-client-helper.h | 6 +- .../include/custom-udp-client.h | 6 +- .../include/custom-udp-server-helper.h | 8 +- .../include/custom-udp-server.h | 25 +- .../src/custom-udp-client.cc | 9 + .../src/custom-udp-server-helper.cc | 3 +- .../src/custom-udp-server.cc | 82 +++-- 22 files changed, 505 insertions(+), 444 deletions(-) delete mode 100644 NS3Mosaik/tcp-server-and-client/test/tcp-tester.cc diff --git a/.gitignore b/.gitignore index cd7074d..c84f27f 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,11 @@ NS3Mosaik/NS3MosaikSim # Ignore files generated by python *.pyc # Ignore files generated by macOS -.DS_Store \ No newline at end of file +.DS_Store +*.pcap +TapControl/monitor_udp.png +TapControl/monitor_tcp.png +TapControl/Monitor.png +TapControl/Monitor.png +NS3Mosaik/NS3MosaikSim +NS3Mosaik/NS3MosaikSim diff --git a/NS3Mosaik/Makefile b/NS3Mosaik/Makefile index 2166fb4..3411f7c 100644 --- a/NS3Mosaik/Makefile +++ b/NS3Mosaik/Makefile @@ -73,7 +73,11 @@ LXFLAGS = -ljsoncpp\ ${NS3_LIB}/libns3.30.1-traffic-control-debug.so\ ${NS3_LIB}/libns3.30.1-stats-debug.so\ ${NS3_LIB}/libns3.30.1-mpi-debug.so\ - + ${NS3_LIB}/libns3.30.1-sixlowpan-debug.so\ + ${NS3_LIB}/libns3.30.1-lr-wpan-debug.so\ + ${NS3_LIB}/libns3.30.1-propagation-debug.so\ + ${NS3_LIB}/libns3.30.1-spectrum-debug.so\ + ${NS3_LIB}/libns3.30.1-antenna-debug.so\ #------------------------# #--- Print Debug Info ---# diff --git a/NS3Mosaik/NS3MosaikSim b/NS3Mosaik/NS3MosaikSim index af2d0dd117b034f42e9267ef830930ed5c12f7c2..81aea98c62499bbd5a2eeba11eadb9666b0522ac 100755 GIT binary patch delta 139574 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

13FYNlTP zDXed1FBV0z)0d(l`j((ZQ48SL~ooEP;W@|BBl1fCZVvHsgHh$*3-n(RpV$A==t-||=Stl>X-Q9KI& zI{jZBAnTtHxe?GOZ-&`fradmQ{Tu&)&nbEw1*xz6WXlTicM7%HjS%?k^w2O{R=oKZ znu%jF@eKZ9U}(54E6VHDVqUMD6K>0i_tCzI?pXPDxb2#_ zEn3WcXNixLQ4zMRmgZ|_fO1fTEhjcsXhFh8xiA8>&9}=;{6xM5bdvdUnTbbxgR&>@ z&IDCDv0y;AdnT9Wy!_EAb!XLKq#0LgLY15N=- z{z|rJ0WO;Fo9$nrje2DP&`IX&W))J?kDxW3R|}gp+PpmHg;dY3hy>5@J0oQPQsOAZ zjwujgBV<&Rt#>5twv)^A;mdcEqijiuM0L7O39_~THF9N?t!tF~Gp*cVzI;2%mJ_wA P+@@su8ggi;E$x2*g`Qu3 delta 121483 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%0AKCToJrr< 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 diff --git a/NS3Mosaik/mosaik_api/include/NS3Netsim.h b/NS3Mosaik/mosaik_api/include/NS3Netsim.h index 233745f..6e0c483 100644 --- a/NS3Mosaik/mosaik_api/include/NS3Netsim.h +++ b/NS3Mosaik/mosaik_api/include/NS3Netsim.h @@ -63,6 +63,7 @@ struct DataXCHG { static vector dataXchgInput; ///< Input data exchange vector static vector dataXchgOutput; ///< Output data exchange vector static map mapIpv4NodeId; ///< Map from client Ipv4 to Node Id +static map> panNetworks; class NS3Netsim { @@ -205,7 +206,7 @@ class NS3Netsim { * \param tcpOrUdp a string that is either set to tcp or udp, indicating which kind of server will be created * \param server holds the server id */ - void setUpServer(InetSocketAddress address, string protocol, string server); + void setUpServer(InetSocketAddress addressIpv4, Inet6SocketAddress addressIpv6, string protocol, string server); /** * Sets up a tcp or udp client depending on what has been passed in @@ -215,7 +216,7 @@ class NS3Netsim { * \param server holds the server id * \param client holds the client id */ - void setUpClient(InetSocketAddress address, string protocol, string server, string client); + void setUpClient(AddressValue addressValue, string protocol, string server, string client); vector< vector> nodeAdjMatrix; ///< Node adjacency matrix string nodeAdjMatrixFilename; ///< Node adjacency matrix filename @@ -225,17 +226,14 @@ class NS3Netsim { vector> arrayNodeCoords; ///< Array of doubles with node coordinates NodeContainer nodes; ///< NS3 container with simulation nodes - PointToPointHelper pointToPoint; ///< Pointer to pointTopoint helper class string LinkRate; ///< Uniform link data rate string LinkDelay; ///< Uniform link delay string LinkErrorRate; ///< Uniform Link error rate uint32_t linkCount; ///< Network link count vector p2pDevices; ///< Vector with all link devices + vector lrWpanDevices; ///< Vector with all lrwpan devices + vector sixlowpanDevices; ///< Vector with all sixlowpan devices - InternetStackHelper internet; ///< Pointer to Internet helper class - Ipv4AddressHelper ipv4Address; ///< Pointer to Ipv4 Internet helper class - - MobilityHelper mobility; ///< Pointer to mobility (position) helper class Ptr nodePositionAlloc; ///< Pointer to node position allocation string appConnectionsFilename; ///< Application client-server connections filename @@ -245,10 +243,10 @@ class NS3Netsim { vector::iterator iList; ///< Application servers vector iterator uint16_t sinkPort; ///< Application port for all server nodes - MultiClientTcpServerHelper multiClientTcpServerHelper = MultiClientTcpServerHelper(Address()); ///< Application TCP server helper + MultiClientTcpServerHelper multiClientTcpServerHelper; ///< Application TCP server helper TcpClientHelper tcpClientHelper = TcpClientHelper(Address()); ///< Application TCP client helper - CustomUdpClientHelper customUdpClientHelper = CustomUdpClientHelper(Address()); ///< Application UDP server helper - CustomUdpServerHelper customUdpServerHelper = CustomUdpServerHelper(Address()); ///< Application UDP client helper + CustomUdpClientHelper customUdpClientHelper = CustomUdpClientHelper(Address()); ///< Application UDP client helper + CustomUdpServerHelper customUdpServerHelper; ///< Application UDP server helper double startTime; ///< Simulation start time int verbose; ///< Verbose level @@ -258,7 +256,6 @@ class NS3Netsim { Ptr sim; ///< Pointer to the smartgrid simulator implementation ApplicationContainer allApplications; - NodeContainer allNodes; string tcpOrUdp; ///< Which network protocol should be used }; diff --git a/NS3Mosaik/mosaik_api/include/ns3-helper.h b/NS3Mosaik/mosaik_api/include/ns3-helper.h index 34e6cd6..63e44ea 100644 --- a/NS3Mosaik/mosaik_api/include/ns3-helper.h +++ b/NS3Mosaik/mosaik_api/include/ns3-helper.h @@ -114,4 +114,13 @@ void PrintIpAddresses(NodeContainer nodes); */ map CreateMapIpv4NodeId(NodeContainer nodes); +/** + * TODO: Reads the files for the LR-WPAN networks that will be created. + * For now returns a fake network to test the LR-WPAN connections + * + * \param lrWpanFileName String, filename of the file that contains information on the LR-WPAN networks + * \returns Map, keys being the center of LR-WPAN and set of nodes being the to that key + */ +map> CreateMapForLRWPAN(string lrWpanFileName); + #endif /* SMARTGRID_NS3_HELPER_H_ */ diff --git a/NS3Mosaik/mosaik_api/src/NS3Netsim.cpp b/NS3Mosaik/mosaik_api/src/NS3Netsim.cpp index 2f532ea..8b39744 100644 --- a/NS3Mosaik/mosaik_api/src/NS3Netsim.cpp +++ b/NS3Mosaik/mosaik_api/src/NS3Netsim.cpp @@ -30,8 +30,12 @@ #include #include "NS3Netsim.h" #include "ns3-helper.h" +#include "ns3/lr-wpan-module.h" +#include "ns3/internet-apps-module.h" +#include "ns3/sixlowpan-module.h" #include "ns3/smartgrid-default-simulator-impl.h" #include +#include using namespace std; using namespace ns3; @@ -58,6 +62,7 @@ ExtractInformationFromPacketAndSendToUpperLayer (Ptr socket) string recMessage = string((char*)buffer); recMessage = recMessage.substr (0,packet->GetSize()); + // TODO: Change this so that we get ipv6 and ipv4 addresses depending on the socket passed in Ipv4Address srcIpv4Address = InetSocketAddress::ConvertFrom (from).GetIpv4(); uint32_t srcNodeId = mapIpv4NodeId[srcIpv4Address]; @@ -66,9 +71,7 @@ ExtractInformationFromPacketAndSendToUpperLayer (Ptr socket) "Pkt Rcv at " << Simulator::Now ().GetMilliSeconds () << " by nodeName: " << Names::FindName(socket->GetNode ()) << " dstNodeId: " << socket->GetNode()->GetId() - << " dstAddr: " << socket->GetNode ()->GetObject()->GetAddress(1,0).GetLocal() << " srcNodeId: " << srcNodeId - << " srcAddr: " << InetSocketAddress::ConvertFrom (from).GetIpv4() << " Size: " << packet->GetSize() << " Payload: " << recMessage << endl; @@ -87,6 +90,15 @@ ExtractInformationFromPacketAndSendToUpperLayer (Ptr socket) stoll(val_time) }; dataXchgOutput.push_back(dataRcv); + + ofstream filePacketsSent; + filePacketsSent.open("packets_rec.pkt", std::ios_base::app); + filePacketsSent << "time: " << Simulator::Now ().GetMilliSeconds () + << " by nodeName: " << Names::FindName(socket->GetNode ()) + << " dstNodeId: " << socket->GetNode()->GetId() + << " srcNodeId: " << srcNodeId + << " Payload: " << recMessage; + filePacketsSent.close(); } NS3Netsim::NS3Netsim(): @@ -95,20 +107,29 @@ NS3Netsim::NS3Netsim(): //--- setup simulation type GlobalValue::Bind ("SimulatorImplementationType", StringValue ("ns3::SmartgridDefaultSimulatorImpl")); +// LogComponentEnable ("Ping6Application", LOG_LEVEL_ALL); +// LogComponentEnable("ArpL3Protocol", LOG_LEVEL_ALL); +// LogComponentEnable("ArpCache", LOG_LEVEL_ALL); // LogComponentEnable("Simulator", LOG_LEVEL_ALL); +// LogComponentEnable("LrWpanCsmaCa", LOG_LEVEL_ALL); +// LogComponentEnable("LrWpanNetDevice", LOG_LEVEL_ALL); +// LogComponentEnable("LrWpanMac", LOG_LEVEL_ALL); // LogComponentEnable("SmartgridDefaultSimulatorImpl", LOG_LEVEL_ALL); -// LogComponentEnable("SmartgridNs3Main", LOG_LEVEL_ALL); + LogComponentEnable("SmartgridNs3Main", LOG_LEVEL_ALL); // LogComponentEnable ("MultiClientTcpServer", LOG_LEVEL_ALL); // LogComponentEnable ("TcpClient", LOG_LEVEL_ALL); // LogComponentEnable ("Socket", LOG_LEVEL_ALL); // LogComponentEnable ("SocketFactory", LOG_LEVEL_ALL); // LogComponentEnable ("TcpSocket", LOG_LEVEL_ALL); // LogComponentEnable ("TcpSocketBase", LOG_LEVEL_ALL); +// LogComponentEnable ("SixLowPanNetDevice", LOG_LEVEL_ALL); // LogComponentEnable ("TcpL4Protocol", LOG_LEVEL_ALL); // LogComponentEnable ("IpL4Protocol", LOG_LEVEL_ALL); // LogComponentEnable ("EventImpl", LOG_LEVEL_ALL); // LogComponentEnable ("Node", LOG_LEVEL_ALL); // LogComponentEnable ("Application", LOG_LEVEL_ALL); +// LogComponentEnable ("Packet", LOG_LEVEL_ALL); +// LogComponentEnable ("Address", LOG_LEVEL_ALL); } @@ -129,6 +150,21 @@ NS3Netsim::init (string f_adjmat, int verb, string s_tcpOrUdp) { + // Point to point helper for point to point connections + PointToPointHelper pointToPoint; + // LrWpanHelper for 802.15.4 wireless communcation + LrWpanHelper lrWpanHelper; + // Internet stack helper to help with installation of internet + InternetStackHelper internet; + // Pointer to Ipv4 Internet helper class + Ipv4AddressHelper ipv4Address; + // Pointer to the Ipv6 Internet helper class + Ipv6AddressHelper ipv6Address; + // Pointer to mobility (position) helper class + MobilityHelper mobility; + // Helper, set up a stack to be used between IPv6 and a generic + SixLowPanHelper sixlowpan; + allApplications = ApplicationContainer (); //--- verbose level verbose = verb; @@ -147,8 +183,10 @@ NS3Netsim::init (string f_adjmat, LinkErrorRate = s_linkErrorRate; linkCount = 0; - //--- set devices properties + //--- set address properties for ipv4 ipv4Address.SetBase ("10.0.0.0", "255.255.255.252"); + //--- set the address properties for ipv6 + ipv6Address.SetBase (Ipv6Address ("2001:2::"), Ipv6Prefix (64)); //--- set application destination port sinkPort = 3030; @@ -192,68 +230,6 @@ NS3Netsim::init (string f_adjmat, Ptr newNode = Names::Find(arrayNamesCoords[m][0]); } - //--- create network topology - NS_LOG_INFO ("Create Links Between Nodes."); - pointToPoint.SetDeviceAttribute ("DataRate", StringValue (LinkRate)); - pointToPoint.SetChannelAttribute ("Delay", StringValue (LinkDelay)); - for (size_t i = 0; i < nodeAdjMatrix.size (); i++) - { - for (size_t j = i; j < nodeAdjMatrix[i].size (); j++) - { - if (nodeAdjMatrix[i][j] == 1) - { - linkCount++; - NodeContainer n_links = NodeContainer (nodes.Get (i), nodes.Get (j)); - NetDeviceContainer n_devs = pointToPoint.Install (n_links); - p2pDevices.push_back(n_devs); - NS_LOG_INFO ("matrix element [" << i << "][" << j << "] is 1"); - } - else - { - NS_LOG_INFO ("matrix element [" << i << "][" << j << "] is 0"); - } - } - } - NS_LOG_INFO(""); - - //--- set link error rate - Ptr em = CreateObject (); - em->SetAttribute ("ErrorRate", DoubleValue (stod(LinkErrorRate))); - for (auto dev = p2pDevices.begin(); dev != p2pDevices.end(); ++dev) - { - (*dev).Get(1)->SetAttribute ("ReceiveErrorModel", PointerValue (em)); - if (verbose > 1) { - std::cout << "int(0) = " << (*dev).Get(0)->GetAddress() - << " int(1) = " << (*dev).Get(1)->GetAddress() - << " ID = " << (*dev).Get(1)->GetNode()->GetId() - << std::endl; - } - } - - - //--- set Internet stack and IP address to the p2p devices - NS_LOG_INFO ("Set internet stack and addresses."); - internet.Install (NodeContainer::GetGlobal ()); - for (auto dev = p2pDevices.begin(); dev != p2pDevices.end(); ++dev) - { - ipv4Address.Assign (*dev); - ipv4Address.NewNetwork (); - } - if (verbose > 1) { - PrintIpAddresses(nodes); - } - - //--- create map Ipv4 address to NodeId - mapIpv4NodeId = CreateMapIpv4NodeId(nodes); - - // --- Global routing protocol for IP version 4 stacks - NS_LOG_INFO ("Initialize Global Routing."); - Ipv4GlobalRoutingHelper::PopulateRoutingTables (); - - //--- Output topology summary - NS_LOG_INFO ("Number of links in the adjacency matrix is: " << linkCount); - NS_LOG_INFO ("Number of all nodes is: " << nodes.GetN ()); - // --- Allocate node positions NS_LOG_INFO ("Allocate Positions to Nodes."); nodePositionAlloc = CreateObject (); @@ -281,12 +257,113 @@ NS3Netsim::init (string f_adjmat, //--- resize list nodeServerList.resize(distance(nodeServerList.begin(), iList)); + // Set the internet stack on every node + internet.Install (NodeContainer::GetGlobal ()); + + //--- create network topology + NS_LOG_INFO ("Create p2p and lr-wpan links Between Nodes, then set internet stack and addresses"); + pointToPoint.SetDeviceAttribute ("DataRate", StringValue (LinkRate)); + pointToPoint.SetChannelAttribute ("Delay", StringValue (LinkDelay)); + for (size_t i = 0; i < nodeAdjMatrix.size (); i++) + { + for (size_t j = i; j < nodeAdjMatrix[i].size (); j++) + { + if (nodeAdjMatrix[i][j] == 1) + { + // Create a point to point link + linkCount++; + NodeContainer n_links = NodeContainer (nodes.Get (i), nodes.Get (j)); + + uint32_t iId = nodes.Get(i)->GetId(); + uint32_t jId = nodes.Get(j)->GetId(); + + NS_LOG_INFO ("matrix element [" << i << "][" << j << "] is " << nodeAdjMatrix[i][j]); + NetDeviceContainer n_devs = pointToPoint.Install (n_links); + p2pDevices.push_back(n_devs); + ipv4Address.Assign (n_devs); + ipv4Address.NewNetwork (); + } + else + { + NS_LOG_INFO ("matrix element [" << i << "][" << j << "] is 0"); + } + } + } + + // Getting PAN network from files + panNetworks = CreateMapForLRWPAN(""); + + // Create the LR-WPAN connections specified in the files with 6LoWPAN + // Iterate through the keys found in the network, the keys act as the center of the PAN + for (auto center = panNetworks.begin(); center != panNetworks.end(); center++) { + // Stores the nodes in the PAN + NodeContainer panNodes; + // Add the center to the list + panNodes.Add(Names::Find((*center).first)); + for (auto spokes = (*center).second.begin(); spokes != (*center).second.end(); spokes++) { + // Add the spokes to the list + panNodes.Add(Names::Find(*spokes)); + } + // Install the LR-WPAN devices + NetDeviceContainer lrwpanDevices = lrWpanHelper.Install(panNodes); + // Fake PAN association and short address assignment. + lrWpanHelper.AssociateToPan (lrwpanDevices, stoi((*center).first)); + // Add Sixlowpan devices + NetDeviceContainer sixlowpanDevices = sixlowpan.Install (lrwpanDevices); + // Add the ipv6 addresses + Ipv6InterfaceContainer deviceInterfaces = ipv6Address.Assign (sixlowpanDevices); + ipv6Address.NewNetwork(); + } + + if (verbose > 1) { + cout << "Printing LR-WPAN network connections read from file" << endl; + for (auto it = panNetworks.begin(); it != panNetworks.end(); it++) { + cout << (*it).first << ";"; + for (auto it2 = (*it).second.begin(); it2 != (*it).second.end(); it2++) { + cout << *it2 << ","; + create((*it).first, *it2); + } + cout << endl; + } + } + + //--- set link error rate + Ptr em = CreateObject (); + em->SetAttribute ("ErrorRate", DoubleValue (stod(LinkErrorRate))); + for (auto dev = p2pDevices.begin(); dev != p2pDevices.end(); ++dev) + { + (*dev).Get(1)->SetAttribute ("ReceiveErrorModel", PointerValue (em)); + if (verbose > 1) { + std::cout << "int(0) = " << (*dev).Get(0)->GetAddress() + << " int(1) = " << (*dev).Get(1)->GetAddress() + << " ID = " << (*dev).Get(1)->GetNode()->GetId() + << std::endl; + } + } + + if (verbose > 1) { + PrintIpAddresses(nodes); + } + + //--- create map Ipv4 address to NodeId + mapIpv4NodeId = CreateMapIpv4NodeId(nodes); + + // --- Global routing protocol for IP version 4 stacks + NS_LOG_INFO ("Initialize Global Routing."); + Ipv4GlobalRoutingHelper::PopulateRoutingTables (); + + //--- Output topology summary + NS_LOG_INFO ("Number of links in the adjacency matrix is: " << linkCount); + NS_LOG_INFO ("Number of all nodes is: " << nodes.GetN ()); //--- set regular trace file AsciiTraceHelper ascii; - pointToPoint.EnableAsciiAll (ascii.CreateFileStream ("traceNS3Netsim.tr")); - //pointToPoint.EnablePcapAll("pcapNS3Netsim.pcap"); - //pointToPoint.EnablePcap("dse", 0, 0, true); +// pointToPoint.EnableAsciiAll (ascii.CreateFileStream ("pointToPointNS3.tr")); +// lrWpanHelper.EnableAsciiAll (ascii.CreateFileStream ("lrWpanHelperNS3.tr")); +// pointToPoint.EnablePcapAll("pcapNS3Netsim.pcap"); +// pointToPoint.EnablePcap("dse", 0, 0, true); +// lrWpanHelper.EnablePcapAll("lrWpanHelperNS3.pcap"); +// lrWpanHelper.EnablePcap("dse", 0, 0, true); } @@ -313,46 +390,54 @@ NS3Netsim::create (string client, string server) break; } } - //--- new connection, create entries if(found == false) { - arrayAppConnections.push_back(record); - - // create server socket - NS_LOG_INFO ("Create server."); - Ptr srvNode = Names::Find(server); - - // Check protocol - - //--- verify if server already exist - std::vector::iterator it = std::find(nodeServerList.begin(), nodeServerList.end(), server); - //--- if not found - if(it == nodeServerList.end()) { - // Create the server application - setUpServer(InetSocketAddress (Ipv4Address::GetAny (), sinkPort), tcpOrUdp, server); - NS_LOG_DEBUG ("NS3Netsim::create Server: " << *iList << endl); - } else { //--- end of server part - NS_LOG_DEBUG ("NS3Netsim::create Server already on the list: " << server << endl); - } - - // create client socket - NS_LOG_INFO ("Create client."); - Ptr dstNode = Names::Find(server); - Ipv4InterfaceAddress sink_iaddr = dstNode->GetObject()->GetAddress (1,0); - InetSocketAddress remote = InetSocketAddress (sink_iaddr.GetLocal(), sinkPort); - setUpClient(remote, tcpOrUdp, server, client); - } + arrayAppConnections.push_back(record); + + // create server socket + NS_LOG_INFO("Create server."); + Ptr srvNode = Names::Find(server); + + Ptr dstNode = Names::Find(server); + + // Check protocol + //--- verify if server already exist + std::vector::iterator it = std::find(nodeServerList.begin(), nodeServerList.end(), server); + //--- if not found + if (it == nodeServerList.end()) { + // Create the server application + setUpServer(InetSocketAddress(Ipv4Address::GetAny(), sinkPort), Inet6SocketAddress(Ipv6Address::GetAny (), sinkPort), tcpOrUdp, server); + NS_LOG_DEBUG("NS3Netsim::create Server: " << *iList << endl); + } else { //--- end of server part + NS_LOG_DEBUG("NS3Netsim::create Server already on the list: " << server << endl); + } + // create client socket + NS_LOG_INFO("Create client."); + // Check if this is part of one of the LR-WPAN networks + // If part of LR-WPAN, use ipv6, otherwise use ipv4 + if (panNetworks.count(server) != 0 && panNetworks[server].count(client) != 0) { + Ipv6InterfaceAddress sink_iaddr = dstNode->GetObject()->GetAddress(1,0); + Inet6SocketAddress remote = Inet6SocketAddress(sink_iaddr.GetAddress(), sinkPort); + setUpClient(AddressValue(remote), tcpOrUdp, server, client); + } else { + Ipv4InterfaceAddress sink_iaddr = dstNode->GetObject()->GetAddress(1,0); + InetSocketAddress remote = InetSocketAddress(sink_iaddr.GetLocal(), sinkPort); + setUpClient(AddressValue(remote), tcpOrUdp, server, client); + } + } } void -NS3Netsim::setUpServer(InetSocketAddress address, string protocol, string server) +NS3Netsim::setUpServer(InetSocketAddress addressIpv4, Inet6SocketAddress addressIpv6, string protocol, string server) { + NS_LOG_FUNCTION(this); // Where the returned application will be stored ApplicationContainer serverAppContainer; // Switch on the protocol passed in if (protocol == "tcp") { // Set the address with which the application should be created - multiClientTcpServerHelper.SetAttribute("Local", AddressValue(address)); + multiClientTcpServerHelper.SetAttribute("LocalIpv4", AddressValue(addressIpv4)); + multiClientTcpServerHelper.SetAttribute("LocalIpv6", AddressValue(addressIpv6)); serverAppContainer = multiClientTcpServerHelper.Install(server); // Set the call back to extract information from a packet and sent it to the upper layer Ptr serverAppAsCorrectType = DynamicCast (serverAppContainer.Get(0)); @@ -360,15 +445,14 @@ NS3Netsim::setUpServer(InetSocketAddress address, string protocol, string server serverAppAsCorrectType->SetPacketReceivedCallBack(ExtractInformationFromPacketAndSendToUpperLayer); } else if (protocol == "udp") { // Set the address with which the application should be created - customUdpServerHelper.SetAttribute("Local", AddressValue(InetSocketAddress (Ipv4Address::GetAny (), sinkPort))); + customUdpServerHelper.SetAttribute("LocalIpv4", AddressValue(addressIpv4)); + customUdpServerHelper.SetAttribute("LocalIpv6", AddressValue(addressIpv6)); // Create a tcp container serverAppContainer = customUdpServerHelper.Install(server); // Set the call back to extract information from a packet and sent it to the upper layer Ptr serverAppAsCorrectType = DynamicCast (serverAppContainer.Get(0)); // Set the function that should be called when the server receives a packet serverAppAsCorrectType->SetPacketReceivedCallBack(ExtractInformationFromPacketAndSendToUpperLayer); - // Set the function that should be called when the server receives a packet - serverAppAsCorrectType->SetPacketReceivedCallBack(ExtractInformationFromPacketAndSendToUpperLayer); } else { // If unknown protocol, stop and throw error NS_FATAL_ERROR("Invalid protocol passed in"); @@ -385,8 +469,9 @@ NS3Netsim::setUpServer(InetSocketAddress address, string protocol, string server } void -NS3Netsim::setUpClient(InetSocketAddress address, string protocol, string server, string client) +NS3Netsim::setUpClient(AddressValue addressValue, string protocol, string server, string client) { + NS_LOG_FUNCTION(this); // Get the server and the client nodes Ptr srcNode = Names::Find(client); Ptr dstNode = Names::Find(server); @@ -395,11 +480,11 @@ NS3Netsim::setUpClient(InetSocketAddress address, string protocol, string server // Switch on the protocol passed in if (protocol == "tcp") { // Create a tcp client - tcpClientHelper.SetAttribute("Remote", AddressValue(address)); + tcpClientHelper.SetAttribute("Remote", addressValue); clientAppContainer = tcpClientHelper.Install(client); } else if (protocol == "udp") { // Create a udp client - customUdpClientHelper.SetAttribute("Remote", AddressValue(address)); + customUdpClientHelper.SetAttribute("Remote", addressValue); clientAppContainer = customUdpClientHelper.Install(client); } else { // If unknown protocol, stop and throw error @@ -429,20 +514,21 @@ NS3Netsim::schedule (string src, string dst, string val, string val_time) << ")" << std::endl; } - if (tcpOrUdp == "tcp") { - Ptr srcNode = Names::Find(src); - Ptr clientApp = DynamicCast (srcNode->GetApplication(0)); - if (clientApp == 0 ){ - clientApp = DynamicCast (srcNode->GetApplication(1)); - } - clientApp->ScheduleTransmit(val, val_time); - } else if (tcpOrUdp == "udp") { - Ptr srcNode = Names::Find(src); - Ptr clientApp = DynamicCast (srcNode->GetApplication(0)); - if (clientApp == 0 ){ - clientApp = DynamicCast (srcNode->GetApplication(1)); + Ptr srcNode = Names::Find(src); + if (srcNode->GetNApplications() > 0) { + if (tcpOrUdp == "tcp") { + Ptr clientApp = DynamicCast (srcNode->GetApplication(0)); + if (clientApp == 0){ + clientApp = DynamicCast (srcNode->GetApplication(1)); + } + clientApp->ScheduleTransmit(val, val_time); + } else if (tcpOrUdp == "udp") { + Ptr clientApp = DynamicCast (srcNode->GetApplication(0)); + if (clientApp == 0){ + clientApp = DynamicCast (srcNode->GetApplication(1)); + } + clientApp->ScheduleTransmit(val, val_time); } - clientApp->ScheduleTransmit(val, val_time); } } @@ -471,10 +557,13 @@ NS3Netsim::runUntil (string nextStop) } } + if (stoi(nextStop) % 100 == 0){ + schedule ("6321", "632", to_string(-stoi(nextStop)), to_string(stoi(nextStop) + 20)); + } + if (verbose > 1) { std::cout << "NS3Netsim::runUntil After_run NS3 time: " << Simulator::Now ().GetMilliSeconds () << std::endl; } - } diff --git a/NS3Mosaik/mosaik_api/src/ns3-helper.cpp b/NS3Mosaik/mosaik_api/src/ns3-helper.cpp index a9bba64..6698597 100644 --- a/NS3Mosaik/mosaik_api/src/ns3-helper.cpp +++ b/NS3Mosaik/mosaik_api/src/ns3-helper.cpp @@ -265,4 +265,13 @@ CreateMapIpv4NodeId(NodeContainer nodes) } return mapIpv4NodeId; +} + +map> CreateMapForLRWPAN(string lrWpanFileName) { + // What will be returned + map> readFromFile; + readFromFile["632"] = set(); + readFromFile["632"].insert("6321"); + readFromFile["632"].insert("6322"); + return readFromFile; } \ No newline at end of file diff --git a/NS3Mosaik/tcp-server-and-client/include/multi-client-tcp-server-helper.h b/NS3Mosaik/tcp-server-and-client/include/multi-client-tcp-server-helper.h index 54e64b3..783e7e3 100644 --- a/NS3Mosaik/tcp-server-and-client/include/multi-client-tcp-server-helper.h +++ b/NS3Mosaik/tcp-server-and-client/include/multi-client-tcp-server-helper.h @@ -22,14 +22,14 @@ * Modelled after packet-sink-helper.h */ +#ifndef _MULTI_CLIENT_TCP_SERVER_HELPER_H_ +#define _MULTI_CLIENT_TCP_SERVER_HELPER_H_ + #include "ns3/object-factory.h" #include "ns3/ipv4-address.h" #include "ns3/node-container.h" #include "ns3/application-container.h" -#ifndef _MULTI_CLIENT_TCP_SERVER_HELPER_H_ -#define _MULTI_CLIENT_TCP_SERVER_HELPER_H_ - using namespace ns3; /** @@ -41,14 +41,14 @@ class MultiClientTcpServerHelper { * \brief constructor * \param address The address for the client that will be created */ - MultiClientTcpServerHelper(Address address); + MultiClientTcpServerHelper(); /** * Sets an attribute to the value passed in * \param name The name of the attribute * \param value The value to which the attribute should be set to */ - void SetAttribute(std::string name, const AttributeValue &value); + void SetAttribute (std::string name, const AttributeValue &value); /** * \brief Installs TcpClient on every node in the NodeContainer @@ -57,7 +57,7 @@ class MultiClientTcpServerHelper { * * \return An application container with all the applications */ - ApplicationContainer Install(NodeContainer c) const; + ApplicationContainer Install (NodeContainer c) const; /** * \brief Installs TcpClient on the given node @@ -66,7 +66,7 @@ class MultiClientTcpServerHelper { * * \return An application container with the installed application */ - ApplicationContainer Install(Ptr node) const; + ApplicationContainer Install (Ptr node) const; /** * \brief Installs TcpClient on a node with nodeName @@ -75,10 +75,10 @@ class MultiClientTcpServerHelper { * * \return An application container with the installed application */ - ApplicationContainer Install(std::string nodeName) const; + ApplicationContainer Install (std::string nodeName) const; private: - Ptr InstallPriv(Ptr node) const; - ObjectFactory m_factory; + Ptr InstallPriv (Ptr node) const; + ObjectFactory m_factory; }; #endif //_MULTI_CLIENT_TCP_SERVER_HELPER_H_ diff --git a/NS3Mosaik/tcp-server-and-client/include/multi-client-tcp-server.h b/NS3Mosaik/tcp-server-and-client/include/multi-client-tcp-server.h index d1aed83..a82c662 100644 --- a/NS3Mosaik/tcp-server-and-client/include/multi-client-tcp-server.h +++ b/NS3Mosaik/tcp-server-and-client/include/multi-client-tcp-server.h @@ -1,4 +1,4 @@ - +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2020 Amrinder S. Grewal * @@ -22,15 +22,15 @@ * Modelled after packet-sink.h */ +#ifndef _MULTI_CLIENT_TCP_SERVER_H_ +#define _MULTI_CLIENT_TCP_SERVER_H_ + #include "ns3/core-module.h" #include "ns3/socket.h" #include "ns3/application.h" #include "ns3/address.h" #include "ns3/ptr.h" -#ifndef _MULTI_CLIENT_TCP_SERVER_H_ -#define _MULTI_CLIENT_TCP_SERVER_H_ - using namespace ns3; /** * \brief Application server that allows multiple simultaneous TCP connection. @@ -44,53 +44,75 @@ using namespace ns3; * * Modelled after packet-sink.h */ -class MultiClientTcpServer : public Application { +class MultiClientTcpServer: public Application +{ public: /** * \brief Get the type ID. * \return the object TypeID */ - static TypeId GetTypeId(void); + static TypeId GetTypeId (void); - MultiClientTcpServer(); - virtual ~MultiClientTcpServer(); + MultiClientTcpServer (); + virtual ~MultiClientTcpServer (); /** - * \return pointer to the listening socket. + * \return pointer to the listening socket with ipv4 address */ - Ptr GetListeningSocket(void) const; + Ptr GetListeningSocketIpv4 (void) const; + + /** + * \return pointer to the listening socket with ipv4 address + */ + Ptr GetListeningSocketIpv6 (void) const; /** * \return list of pointer to accepted sockets */ - std::list> GetAcceptedSockets(void) const; + std::list > GetAcceptedSockets(void) const; /** * \brief set the callback function that is called when a packet is received * \param callback the function to which the callback is set. */ void SetPacketReceivedCallBack(void (*callback)(Ptr socket)); + + Address m_localIpv4; //!< Local address to bind to for ipv4 socket + Address m_localIpv6; //!< Local address to bind to for the ipv6 socket protected: - virtual void DoDispose(void); + virtual void DoDispose (void); private: // inherited from Application base class. - virtual void StartApplication(void); // Called at time specified by Start - virtual void StopApplication(void); // Called at time specified by Stop + virtual void StartApplication (void); // Called at time specified by Start + virtual void StopApplication (void); // Called at time specified by Stop + + /** + * \brief Created to set up the listening socket with all the callbacks set. + * \param address of type Address, the address which will bind to the socket + * \return Ptr, the socket with the address bound + */ + Ptr CreateListeningSocket(const Address bindTo); + + /** + * \breif Closes the listening sockets. + * \param The socket to close + */ + void CloseListeningSocket(Ptr socket); /** * \brief Handle a connection request received by the application. * \param socket the incoming connection socket * \param from the address the connection is from */ - bool HandleRequest(Ptr socket, const Address &from); + bool HandleRequest(Ptr socket, const Address& from); /** * \brief Handle an incoming connection that has been accepted * \param socket the incoming connection socket * \param from the address the connection is from */ - void HandleAccept(Ptr socket, const Address &from); + void HandleAccept(Ptr socket, const Address& from); /** * \brief Handle a packet received by the application @@ -102,21 +124,21 @@ class MultiClientTcpServer : public Application { * \brief Handle an connection close * \param socket the connected socket */ - void HandlePeerClose(Ptr socket); + void HandlePeerClose (Ptr socket); /** * \brief Handle an connection error * \param socket the connected socket */ - void HandlePeerError(Ptr socket); + void HandlePeerError (Ptr socket); // When a connection is accepted in TCP, a new socket is returned // So we need to store a listening socket for this class - Ptr m_listeningSocket; //!< Listening socket + Ptr m_listeningSocketIpv4; //!< Listening socket for ipv4 + Ptr m_listeningSocketIpv6; //!< Listening socket for ipv6 // And a list of sockets that have been accepted - std::list> m_acceptedSocketList; //!< the accepted sockets + std::list > m_acceptedSocketList; //!< the accepted sockets - Address m_local; //!< Local address to bind to /// Traced Callback: received packets, source address. TracedCallback, const Address &> m_rxTrace; diff --git a/NS3Mosaik/tcp-server-and-client/include/tcp-client-helper.h b/NS3Mosaik/tcp-server-and-client/include/tcp-client-helper.h index a8e0f17..f39db28 100644 --- a/NS3Mosaik/tcp-server-and-client/include/tcp-client-helper.h +++ b/NS3Mosaik/tcp-server-and-client/include/tcp-client-helper.h @@ -22,13 +22,13 @@ * Modelled after udp-client-server-helper.h */ +#ifndef _TCP_CLIENT_HELPER_H_ +#define _TCP_CLIENT_HELPER_H_ + #include "ns3/node-container.h" #include "ns3/application-container.h" #include "ns3/core-module.h" -#ifndef _TCP_CLIENT_HELPER_H_ -#define _TCP_CLIENT_HELPER_H_ - using namespace ns3; /** diff --git a/NS3Mosaik/tcp-server-and-client/include/tcp-client.h b/NS3Mosaik/tcp-server-and-client/include/tcp-client.h index 0120f90..04eea5b 100644 --- a/NS3Mosaik/tcp-server-and-client/include/tcp-client.h +++ b/NS3Mosaik/tcp-server-and-client/include/tcp-client.h @@ -22,15 +22,15 @@ * Modelled after udp-echo-client.h */ +#ifndef _TCP_CLIENT_H_ +#define _TCP_CLIENT_H_ + #include "ns3/socket.h" #include "ns3/application.h" #include "ns3/address.h" #include "ns3/ptr.h" #include "ns3/traced-callback.h" -#ifndef _TCP_SENSOR_H_ -#define _TCP_SENSOR_H_ - using namespace ns3; /** @@ -107,4 +107,4 @@ class TcpClient : public Application TracedCallback, const Address &, const Address &> m_rxTraceWithAddresses; }; -#endif //_TCP_SENSOR_H_ +#endif //_TCP_CLIENT_H_ diff --git a/NS3Mosaik/tcp-server-and-client/src/multi-client-tcp-server-helper.cc b/NS3Mosaik/tcp-server-and-client/src/multi-client-tcp-server-helper.cc index 397f75a..82bd68f 100644 --- a/NS3Mosaik/tcp-server-and-client/src/multi-client-tcp-server-helper.cc +++ b/NS3Mosaik/tcp-server-and-client/src/multi-client-tcp-server-helper.cc @@ -29,10 +29,9 @@ using namespace ns3; -MultiClientTcpServerHelper::MultiClientTcpServerHelper(Address address) +MultiClientTcpServerHelper::MultiClientTcpServerHelper() { m_factory.SetTypeId ("ns3::MultiClientTcpServer"); - m_factory.Set ("Local", AddressValue (address)); } void diff --git a/NS3Mosaik/tcp-server-and-client/src/multi-client-tcp-server.cc b/NS3Mosaik/tcp-server-and-client/src/multi-client-tcp-server.cc index f7f7681..b636d9b 100644 --- a/NS3Mosaik/tcp-server-and-client/src/multi-client-tcp-server.cc +++ b/NS3Mosaik/tcp-server-and-client/src/multi-client-tcp-server.cc @@ -26,7 +26,6 @@ #include "ns3/address-utils.h" #include "ns3/socket-factory.h" #include "multi-client-tcp-server.h" -#include "multi-use-code.h" using namespace ns3; @@ -40,11 +39,16 @@ MultiClientTcpServer::GetTypeId (void) .SetParent () .SetGroupName("Applications") .AddConstructor () - .AddAttribute("Local", + .AddAttribute("LocalIpv4", "The value on which to Bind the rx socket.", AddressValue (), - MakeAddressAccessor (&MultiClientTcpServer::m_local), + MakeAddressAccessor (&MultiClientTcpServer::m_localIpv4), MakeAddressChecker()) + .AddAttribute("LocalIpv6", + "The value on which to Bind the rx socket.", + AddressValue (), + MakeAddressAccessor (&MultiClientTcpServer::m_localIpv6), + MakeAddressChecker()) .AddTraceSource("Rx", "A packet has been received", MakeTraceSourceAccessor (&MultiClientTcpServer::m_rxTrace), @@ -61,7 +65,8 @@ MultiClientTcpServer::MultiClientTcpServer() { NS_LOG_FUNCTION(this); // Set the socket to null - m_listeningSocket = 0; + m_listeningSocketIpv4 = 0; + m_listeningSocketIpv6 = 0; m_packetReceivedCallback = 0; } @@ -71,10 +76,17 @@ MultiClientTcpServer::~MultiClientTcpServer() } Ptr -MultiClientTcpServer::GetListeningSocket (void) const +MultiClientTcpServer::GetListeningSocketIpv4 (void) const { NS_LOG_FUNCTION (this); - return m_listeningSocket; + return m_listeningSocketIpv4; +} + +Ptr +MultiClientTcpServer::GetListeningSocketIpv6 (void) const +{ + NS_LOG_FUNCTION (this); + return m_listeningSocketIpv6; } std::list > @@ -89,7 +101,8 @@ MultiClientTcpServer::DoDispose (void) { NS_LOG_FUNCTION (this); // Clear the listening socket - m_listeningSocket = 0; + m_listeningSocketIpv4 = 0; + m_listeningSocketIpv6 = 0; // Clear the accepted socket m_acceptedSocketList.clear (); @@ -108,36 +121,50 @@ void MultiClientTcpServer::StartApplication() { NS_LOG_FUNCTION(this); - // Create the socket if it does not already exist - if (m_listeningSocket == 0) { - TypeId tid = TypeId::LookupByName ("ns3::TcpSocketFactory"); - m_listeningSocket = Socket::CreateSocket(GetNode(), tid); - if (m_listeningSocket->Bind(m_local) == -1) - { - NS_FATAL_ERROR ("Failed to bind socket"); - } - - m_listeningSocket->Listen(); - m_listeningSocket->ShutdownSend (); - // No need to worry about multi-cast, not appropriate for TCP - } + // Create ipv4 listening socket if it does not exist + if (m_listeningSocketIpv4 == 0) { + m_listeningSocketIpv4 = CreateListeningSocket(m_localIpv4); + } + + // Create ipv6 listening socket if it does not exist + if (m_listeningSocketIpv6 == 0) { + m_listeningSocketIpv6 = CreateListeningSocket(m_localIpv6); + } +} + +Ptr +MultiClientTcpServer::CreateListeningSocket(const Address bindTo) +{ + NS_LOG_FUNCTION(this); + // Create the socket + TypeId tid = TypeId::LookupByName ("ns3::TcpSocketFactory"); + Ptr socket = Socket::CreateSocket(GetNode(), tid); + // Bind the socket + if (socket->Bind(bindTo) == -1) + { + NS_FATAL_ERROR ("Failed to bind socket"); + } + + // Tell the socket to start listening + socket->Listen(); + socket->ShutdownSend (); // Set the callback funcs for connection request and connection accept - m_listeningSocket->SetAcceptCallback( - MakeCallback (&MultiClientTcpServer::HandleRequest, this), - MakeCallback (&MultiClientTcpServer::HandleAccept, this) + socket->SetAcceptCallback( + MakeCallback (&MultiClientTcpServer::HandleRequest, this), + MakeCallback (&MultiClientTcpServer::HandleAccept, this) ); - // Set the callback funcs for connection close for the listening socket - m_listeningSocket->SetCloseCallbacks( - MakeCallback (&MultiClientTcpServer::HandlePeerClose, this), - MakeCallback (&MultiClientTcpServer::HandlePeerError, this) + socket->SetCloseCallbacks( + MakeCallback (&MultiClientTcpServer::HandlePeerClose, this), + MakeCallback (&MultiClientTcpServer::HandlePeerError, this) ); - // Set the call back for packet reception for the listening socket - m_listeningSocket->SetRecvCallback( - MakeCallback(&MultiClientTcpServer::HandleRead, this) + socket->SetRecvCallback( + MakeCallback(&MultiClientTcpServer::HandleRead, this) ); + + return socket; } void @@ -146,18 +173,35 @@ MultiClientTcpServer::StopApplication() NS_LOG_FUNCTION (this); // Iterate thorough and close all sockets that are still active. while(!m_acceptedSocketList.empty ()) //these are accepted sockets, close them - { - Ptr acceptedSocket = m_acceptedSocketList.front (); - m_acceptedSocketList.pop_front (); - acceptedSocket->Close (); - } + { + Ptr acceptedSocket = m_acceptedSocketList.front (); + m_acceptedSocketList.pop_front (); + acceptedSocket->Close (); + } + + // Close the listening sockets + if (m_listeningSocketIpv4 != 0) + { + CloseListeningSocket(m_listeningSocketIpv4); + } + if (m_listeningSocketIpv6 != 0) + { + CloseListeningSocket(m_listeningSocketIpv6); + } +} - // Close the listening socket - if (m_listeningSocket != 0) - { - m_listeningSocket->Close (); - m_listeningSocket->SetRecvCallback (MakeNullCallback > ()); - } +void +MultiClientTcpServer::CloseListeningSocket(Ptr socket) +{ + NS_LOG_FUNCTION(this); + socket->Close (); + socket->SetAcceptCallback ( + MakeNullCallback, const Address& > (), + MakeNullCallback, const Address & > ()); + socket->SetCloseCallbacks ( + MakeNullCallback > (), + MakeNullCallback > ()); + socket->SetRecvCallback (MakeNullCallback > ()); } bool MultiClientTcpServer::HandleRequest(Ptr socket, const Address& from) @@ -198,4 +242,4 @@ MultiClientTcpServer::HandleRead(Ptr socket) { { m_packetReceivedCallback(socket); } -} \ No newline at end of file +} diff --git a/NS3Mosaik/tcp-server-and-client/src/tcp-client.cc b/NS3Mosaik/tcp-server-and-client/src/tcp-client.cc index 0c9b89b..c2a2506 100644 --- a/NS3Mosaik/tcp-server-and-client/src/tcp-client.cc +++ b/NS3Mosaik/tcp-server-and-client/src/tcp-client.cc @@ -35,6 +35,8 @@ #include "ns3/uinteger.h" #include "ns3/trace-source-accessor.h" #include "ns3/ipv4.h" +#include "ns3/ipv6.h" +#include "ns3/names.h" #include "tcp-client.h" #include @@ -118,29 +120,12 @@ void TcpClient::StartApplication (void) { NS_LOG_FUNCTION(this); - // Make a socket if empty if (m_socket == 0) { TypeId tid = TypeId::LookupByName ("ns3::TcpSocketFactory"); m_socket = Socket::CreateSocket (GetNode (), tid); - if (Ipv4Address::IsMatchingType(m_peerAddress) == true) - { - if (m_socket->Bind () == -1) - { - NS_FATAL_ERROR ("Failed to bind socket"); - } - m_socket->Connect (InetSocketAddress (Ipv4Address::ConvertFrom(m_peerAddress), m_peerPort)); - } - else if (Ipv6Address::IsMatchingType(m_peerAddress) == true) - { - if (m_socket->Bind6 () == -1) - { - NS_FATAL_ERROR ("Failed to bind socket"); - } - m_socket->Connect (Inet6SocketAddress (Ipv6Address::ConvertFrom(m_peerAddress), m_peerPort)); - } - else if (InetSocketAddress::IsMatchingType (m_peerAddress) == true) + if (InetSocketAddress::IsMatchingType (m_peerAddress) == true) { if (m_socket->Bind () == -1) { @@ -185,6 +170,16 @@ TcpClient::SendMessage (string message) Ptr sendPacket = Create ((uint8_t*)message.c_str(),message.size()); m_socket->Send (sendPacket); + + ofstream filePacketsSent; + filePacketsSent.open("packets_sent.pkt", std::ios_base::app); + filePacketsSent << "time: " << Simulator::Now ().GetMilliSeconds () + << " nodeId: " << m_socket->GetNode()->GetId() + << " by nodeName: " << Names::FindName(m_socket->GetNode ()) + << " MsgSize: " << message.size() << std::endl; + filePacketsSent.close(); + } else { + std::cout << "m_socket is 0" << std::endl; } } @@ -198,7 +193,6 @@ TcpClient::ScheduleTransmit(std::string val, std::string valTime) { << " Event_Val_Time: " << valTime << " val " << val << " socket " << m_socket); NS_LOG_DEBUG("TcpClient:schedule(" -// << "source=" << m_socket->GetNode () << ", value=" << val << ", delay=" << schDelay << ")"); diff --git a/NS3Mosaik/tcp-server-and-client/test/tcp-tester.cc b/NS3Mosaik/tcp-server-and-client/test/tcp-tester.cc deleted file mode 100644 index 2b70c97..0000000 --- a/NS3Mosaik/tcp-server-and-client/test/tcp-tester.cc +++ /dev/null @@ -1,172 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Add lines here - * Copyright (c) 2020 Amrinder S. Grewal - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Amrinder S. Grewal - * Date: 2020.05.18 - * Company: University of Alberta/Canada - Computing Science - * - * File modelled after star.cc - */ - -#include "ns3/core-module.h" -#include "ns3/network-module.h" -#include "ns3/netanim-module.h" -#include "ns3/internet-module.h" -#include "ns3/point-to-point-module.h" -#include "ns3/applications-module.h" -#include "ns3/point-to-point-layout-module.h" -#include "ns3/simulator.h" -#include -#include "ns3/Ptr.h" - -// Network topology (default) -// -// n2 n3 n4 . -// \ | / . -// \|/ . -// n1--- n0---n5 . -// /|\ . -// / | \ . -// n8 n7 n6 . -// n0 will always exist and be the server, n1....nk will be the number of clients -// Having 0 clients is a possibility - -using namespace ns3; - -NS_LOG_COMPONENT_DEFINE ("TESTER"); - - -void -ReceiveMessage (Ptr socket) -{ - Address from; - Ptr packet = socket->RecvFrom (from); - if (packet != 0) { - packet->RemoveAllPacketTags (); - packet->RemoveAllByteTags (); - - Ptr recvnode = socket->GetNode(); - uint8_t *buffer = new uint8_t[packet->GetSize()]; - packet->CopyData(buffer,packet->GetSize()); - std::string recMessage = std::string((char*)buffer); - recMessage = recMessage.substr (0,packet->GetSize()); - -// Ipv4Address srcIpv4Address = InetSocketAddress::ConvertFrom(from).GetIpv4(); -// uint32_t srcNodeId = mapIpv4NodeId[srcIpv4Address]; - - //--- print received msg - NS_LOG_DEBUG( - "Pkt Rcv at " << Simulator::Now ().GetMilliSeconds () - << " dstAddr: " << socket->GetNode ()->GetObject()->GetAddress(1,0).GetLocal() - << " srcAddr: " << InetSocketAddress::ConvertFrom (from).GetIpv4() - << " Size: " << packet->GetSize() - << " Payload: " << recMessage - ); - } -} - - -int -main (int argc, char *argv[]) -{ - // - // Default number of nodes in the star. Overridable by command line argument. - // - uint32_t nSpokes = 10; - - CommandLine cmd; - cmd.AddValue ("nSpokes", "Number of nodes to place in the star", nSpokes); - cmd.Parse (argc, argv); - - LogComponentEnable ("MultiClientTcpServer", LOG_LEVEL_ALL); - LogComponentEnable ("TESTER", LOG_LEVEL_DEBUG); - LogComponentEnable ("TcpClient", LOG_LEVEL_ALL); -// LogComponentEnable ("TcpL4Protocol", LOG_LEVEL_ALL); - - NS_LOG_INFO ("Build star topology."); - PointToPointHelper pointToPoint; - pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps")); - pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms")); - PointToPointStarHelper star (nSpokes, pointToPoint); - - NS_LOG_INFO ("Install internet stack on all nodes."); - InternetStackHelper internet; - star.InstallStack (internet); - - NS_LOG_INFO ("Assign IP Addresses."); - star.AssignIpv4Addresses (Ipv4AddressHelper ("10.1.1.0", "255.255.255.0")); - - NS_LOG_INFO ("Create applications."); - // - // Create a packet sink on the star "hub" to receive packets. - // - uint16_t port = 50000; - Address hubLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port)); - MultiClientTcpServerHelper multiClientTcpServerHelper (hubLocalAddress); - ApplicationContainer hubApp = multiClientTcpServerHelper.Install (star.GetHub ()); - Ptr server = DynamicCast (hubApp.Get(0)); - server->SetPacketReceivedCallBack(&ReceiveMessage); - - hubApp.Start (Seconds (0.0)); - hubApp.Stop (Seconds (9.0)); - - // - // Create client applications to send TCP to the hub, one on each spoke node. - // - TcpClientHelper helper = TcpClientHelper(Address()); - ApplicationContainer spokeApps; - for (uint32_t i = 0; i < star.SpokeCount (); ++i) - { - AddressValue remoteAddress (InetSocketAddress (star.GetHubIpv4Address(i), port)); - helper.SetAttribute("Remote", remoteAddress); - helper.Install (star.GetSpokeNode (i)); - Ptr client = DynamicCast (star.GetSpokeNode(i)->GetApplication(0)); - - for (int j = 0; j < 10000; j++) { - Simulator::Schedule( - MilliSeconds(1000), - &TcpClient::ScheduleTransmit, - client, - std::to_string(i + 0.5), - std::to_string(i + 2000) - ); - } - spokeApps.Add (ApplicationContainer(client)); - } - spokeApps.Start (Seconds (0.0)); - spokeApps.Stop (Seconds (10.0)); - - NS_LOG_INFO ("Enable static global routing."); - // - // Turn on global static routing so we can actually be routed across the star. - // - Ipv4GlobalRoutingHelper::PopulateRoutingTables (); - - NS_LOG_INFO ("Enable pcap tracing."); - // - // Do pcap tracing on all point-to-point devices on all nodes. - // - pointToPoint.EnablePcapAll ("star"); - - NS_LOG_INFO ("Run Simulation."); - Simulator::Run (); - Simulator::Destroy (); - NS_LOG_INFO ("Done."); - - return 0; -} \ No newline at end of file diff --git a/NS3Mosaik/udp-server-client/include/custom-udp-client-helper.h b/NS3Mosaik/udp-server-client/include/custom-udp-client-helper.h index eb1cb48..5c20dfb 100644 --- a/NS3Mosaik/udp-server-client/include/custom-udp-client-helper.h +++ b/NS3Mosaik/udp-server-client/include/custom-udp-client-helper.h @@ -22,14 +22,14 @@ * Modelled after packet-sink-helper.h */ +#ifndef _CUSTOM_UDP_CLIENT_HELPER_H_ +#define _CUSTOM_UDP_CLIENT_HELPER_H_ + #include "ns3/object-factory.h" #include "ns3/ipv4-address.h" #include "ns3/node-container.h" #include "ns3/application-container.h" -#ifndef _CUSTOM_UDP_CLIENT_HELPER_H_ -#define _CUSTOM_UDP_CLIENT_HELPER_H_ - using namespace ns3; /** diff --git a/NS3Mosaik/udp-server-client/include/custom-udp-client.h b/NS3Mosaik/udp-server-client/include/custom-udp-client.h index f973e6a..d1261ea 100644 --- a/NS3Mosaik/udp-server-client/include/custom-udp-client.h +++ b/NS3Mosaik/udp-server-client/include/custom-udp-client.h @@ -21,15 +21,15 @@ * */ +#ifndef _CUSTOM_UDP_CLIENT_H_ +#define _CUSTOM_UDP_CLIENT_H_ + #include "ns3/socket.h" #include "ns3/application.h" #include "ns3/address.h" #include "ns3/ptr.h" #include "ns3/traced-callback.h" -#ifndef _CUSTOM_UDP_CLIENT_H_ -#define _CUSTOM_UDP_CLIENT_H_ - using namespace ns3; using namespace std; diff --git a/NS3Mosaik/udp-server-client/include/custom-udp-server-helper.h b/NS3Mosaik/udp-server-client/include/custom-udp-server-helper.h index ebd6dbc..6c71407 100644 --- a/NS3Mosaik/udp-server-client/include/custom-udp-server-helper.h +++ b/NS3Mosaik/udp-server-client/include/custom-udp-server-helper.h @@ -22,14 +22,14 @@ * Modelled after packet-sink-helper.h */ +#ifndef _CUSTOM_UDP_SERVER_HELPER_H_ +#define _CUSTOM_UDP_SERVER_HELPER_H_ + #include "ns3/object-factory.h" #include "ns3/ipv4-address.h" #include "ns3/node-container.h" #include "ns3/application-container.h" -#ifndef _CUSTOM_UDP_SERVER_HELPER_H_ -#define _CUSTOM_UDP_SERVER_HELPER_H_ - using namespace ns3; /** @@ -41,7 +41,7 @@ class CustomUdpServerHelper { * \brief constructor * \param address The address for the client that will be created */ - CustomUdpServerHelper(Address address); + CustomUdpServerHelper(); /** * Sets an attribute to the value passed in diff --git a/NS3Mosaik/udp-server-client/include/custom-udp-server.h b/NS3Mosaik/udp-server-client/include/custom-udp-server.h index 518d374..bf81dae 100644 --- a/NS3Mosaik/udp-server-client/include/custom-udp-server.h +++ b/NS3Mosaik/udp-server-client/include/custom-udp-server.h @@ -21,15 +21,15 @@ * */ +#ifndef _CUSTOM_UDP_SERVER_H_ +#define _CUSTOM_UDP_SERVER_H_ + #include "ns3/core-module.h" #include "ns3/socket.h" #include "ns3/application.h" #include "ns3/address.h" #include "ns3/ptr.h" -#ifndef _CUSTOM_UDP_SERVER_H_ -#define _CUSTOM_UDP_SERVER_H_ - using namespace ns3; using namespace std; @@ -51,6 +51,19 @@ class CustomUdpServer: public Application { private: virtual void StartApplication (void); virtual void StopApplication (void); + + /** + * \Brief, create a udp socket and bind it to the address + * \param bindTo, the address to which the udp packet should be bound to + * \return socket, the created udp socket + */ + Ptr CreateSocket(const Address bindTo); + + /** + * Close a udp socket. + * \param socket, the udp socket to close + */ + void CloseSocket(Ptr socket); /** * The over-written read callback function that calls ExtractInformationFromPacketAndSendToUpperLayer to send * a message that a new packet has been received. @@ -58,8 +71,10 @@ class CustomUdpServer: public Application { virtual void HandleRead (Ptr socket); /// The function that will be called when a packet is received void (*m_packetReceivedCallback)(Ptr socket); - Ptr m_socket; //!< Socket that will be used to send the messages - Address m_local; //!< Local address to bind to + Ptr m_socketIpv4; //!< Socket that will be used to send the messages for ipv4 + Ptr m_socketIpv6; //!< Socket that will be used to send the messages for ipv6 + Address m_localIpv4; //!< Local address to bind to for ipv4 socket + Address m_localIpv6; //!< Local address to bind to for ipv4 socket TracedCallback > m_rxTrace; TracedCallback, const Address &, const Address &> m_rxTraceWithAddresses; diff --git a/NS3Mosaik/udp-server-client/src/custom-udp-client.cc b/NS3Mosaik/udp-server-client/src/custom-udp-client.cc index 1e93103..aa94f93 100644 --- a/NS3Mosaik/udp-server-client/src/custom-udp-client.cc +++ b/NS3Mosaik/udp-server-client/src/custom-udp-client.cc @@ -35,6 +35,7 @@ #include "ns3/uinteger.h" #include "ns3/trace-source-accessor.h" #include "ns3/ipv4.h" +#include "ns3/names.h" #include "ns3/log.h" #include @@ -85,6 +86,14 @@ CustomUdpClient::SendMessage (string message) Ptr sendPacket = Create ((uint8_t *) message.c_str (), message.size ()); m_socket->Send (sendPacket); + + ofstream filePacketsSent; + filePacketsSent.open("packets_sent.pkt", std::ios_base::app); + filePacketsSent << "time: " << Simulator::Now ().GetMilliSeconds () + << " nodeId: " << m_socket->GetNode()->GetId() + << " by nodeName: " << Names::FindName(m_socket->GetNode ()) + << " MsgSize: " << message.size() << std::endl; + filePacketsSent.close(); } } diff --git a/NS3Mosaik/udp-server-client/src/custom-udp-server-helper.cc b/NS3Mosaik/udp-server-client/src/custom-udp-server-helper.cc index 0cc8d89..5b73087 100644 --- a/NS3Mosaik/udp-server-client/src/custom-udp-server-helper.cc +++ b/NS3Mosaik/udp-server-client/src/custom-udp-server-helper.cc @@ -29,10 +29,9 @@ using namespace ns3; -CustomUdpServerHelper::CustomUdpServerHelper(Address address) +CustomUdpServerHelper::CustomUdpServerHelper() { m_factory.SetTypeId ("ns3::CustomUdpServer"); - m_factory.Set ("Local", AddressValue (address)); } void diff --git a/NS3Mosaik/udp-server-client/src/custom-udp-server.cc b/NS3Mosaik/udp-server-client/src/custom-udp-server.cc index e03f285..872dd34 100644 --- a/NS3Mosaik/udp-server-client/src/custom-udp-server.cc +++ b/NS3Mosaik/udp-server-client/src/custom-udp-server.cc @@ -49,11 +49,16 @@ CustomUdpServer::GetTypeId (void) .SetParent () .SetGroupName("Applications") .AddConstructor () - .AddAttribute("Local", - "The value on which to Bind the rx socket.", - AddressValue (), - MakeAddressAccessor (&CustomUdpServer::m_local), - MakeAddressChecker()) + .AddAttribute("LocalIpv4", + "The value on which to Bind the rx socket.", + AddressValue (), + MakeAddressAccessor (&CustomUdpServer::m_localIpv4), + MakeAddressChecker()) + .AddAttribute("LocalIpv6", + "The value on which to Bind the rx socket.", + AddressValue (), + MakeAddressAccessor (&CustomUdpServer::m_localIpv6), + MakeAddressChecker()) .AddTraceSource ("Rx", "A packet has been received", MakeTraceSourceAccessor (&CustomUdpServer::m_rxTrace), "ns3::Packet::TracedCallback") @@ -85,32 +90,63 @@ CustomUdpServer::StartApplication (void) { NS_LOG_FUNCTION(this); // Create the socket if it does not already exist - if (m_socket == 0) { - TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory"); - m_socket = Socket::CreateSocket(GetNode(), tid); - if (m_socket->Bind(m_local) == -1) - { - NS_FATAL_ERROR ("Failed to bind socket"); - } + if (m_socketIpv4 == 0) + { + m_socketIpv4 = CreateSocket(m_localIpv4); + } - m_socket->Listen(); - m_socket->ShutdownSend (); - // No need to worry about multi-cast, not appropriate for TCP - } + if (m_socketIpv6 == 0) + { + m_socketIpv6 = CreateSocket(m_localIpv6); + } +} + +Ptr +CustomUdpServer::CreateSocket(const Address bindTo) +{ + NS_LOG_FUNCTION(this); + Ptr socket; + // Create a socket + TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory"); + socket = Socket::CreateSocket(GetNode(), tid); + // Bind teh socket + if (socket->Bind(bindTo) == -1) + { + NS_FATAL_ERROR ("Failed to bind socket"); + } + + // Tell the socket to listen + socket->Listen(); + socket->ShutdownSend (); + // No need to worry about multi-cast, not appropriate for TCP // Set the call back for packet reception for the listening socket - m_socket->SetRecvCallback( - MakeCallback(&CustomUdpServer::HandleRead, this) + socket->SetRecvCallback( + MakeCallback(&CustomUdpServer::HandleRead, this) ); + + return socket; } void CustomUdpServer::StopApplication (void) { // Close the socket - if (m_socket != 0) - { - m_socket->Close (); - m_socket->SetRecvCallback (MakeNullCallback > ()); - } + if (m_socketIpv4 != 0) + { + CloseSocket(m_socketIpv4); + } + + if (m_socketIpv6 != 0) + { + CloseSocket(m_socketIpv6); + } +} + +void +CustomUdpServer::CloseSocket(Ptr socket) +{ + NS_LOG_FUNCTION(this); + socket->Close (); + socket->SetRecvCallback (MakeNullCallback > ()); } \ No newline at end of file From f20e5cc30e549bada666a1611e7b635c72bea8df Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Wed, 8 Jul 2020 15:15:19 -0600 Subject: [PATCH 02/22] Wireless capabalities changed to Wifi from LR-WPAN - Wifi being installed on required nodes - Packets being sent and received over wifi in the wireless network at the end node. - This is only a toy example. More testing needs to be done to make sure this works reliably. --- NS3Mosaik/Makefile | 2 + NS3Mosaik/mosaik_api/src/NS3Netsim.cpp | 103 ++++++++++++++++--------- 2 files changed, 68 insertions(+), 37 deletions(-) diff --git a/NS3Mosaik/Makefile b/NS3Mosaik/Makefile index 3411f7c..b12b046 100644 --- a/NS3Mosaik/Makefile +++ b/NS3Mosaik/Makefile @@ -78,6 +78,8 @@ LXFLAGS = -ljsoncpp\ ${NS3_LIB}/libns3.30.1-propagation-debug.so\ ${NS3_LIB}/libns3.30.1-spectrum-debug.so\ ${NS3_LIB}/libns3.30.1-antenna-debug.so\ + ${NS3_LIB}/libns3.30.1-wifi-debug.so\ + ${NS3_LIB}/libns3.30.1-energy-debug.so\ #------------------------# #--- Print Debug Info ---# diff --git a/NS3Mosaik/mosaik_api/src/NS3Netsim.cpp b/NS3Mosaik/mosaik_api/src/NS3Netsim.cpp index 8b39744..74a7053 100644 --- a/NS3Mosaik/mosaik_api/src/NS3Netsim.cpp +++ b/NS3Mosaik/mosaik_api/src/NS3Netsim.cpp @@ -28,14 +28,16 @@ //--- Includes ---// #include -#include "NS3Netsim.h" -#include "ns3-helper.h" +#include +#include #include "ns3/lr-wpan-module.h" +#include "ns3/core-module.h" #include "ns3/internet-apps-module.h" +#include "ns3/wifi-module.h" #include "ns3/sixlowpan-module.h" #include "ns3/smartgrid-default-simulator-impl.h" -#include -#include +#include "NS3Netsim.h" +#include "ns3-helper.h" using namespace std; using namespace ns3; @@ -63,15 +65,15 @@ ExtractInformationFromPacketAndSendToUpperLayer (Ptr socket) recMessage = recMessage.substr (0,packet->GetSize()); // TODO: Change this so that we get ipv6 and ipv4 addresses depending on the socket passed in - Ipv4Address srcIpv4Address = InetSocketAddress::ConvertFrom (from).GetIpv4(); - uint32_t srcNodeId = mapIpv4NodeId[srcIpv4Address]; +// Ipv4Address srcIpv4Address = InetSocketAddress::ConvertFrom (from).GetIpv4(); +// uint32_t srcNodeId = mapIpv4NodeId[srcIpv4Address]; //--- print received msg NS_LOG_DEBUG( "Pkt Rcv at " << Simulator::Now ().GetMilliSeconds () << " by nodeName: " << Names::FindName(socket->GetNode ()) << " dstNodeId: " << socket->GetNode()->GetId() - << " srcNodeId: " << srcNodeId +// << " srcNodeId: " << srcNodeId << " Size: " << packet->GetSize() << " Payload: " << recMessage << endl; @@ -84,20 +86,20 @@ ExtractInformationFromPacketAndSendToUpperLayer (Ptr socket) string val_time = recMessage.substr(current+1); //--- insert data on dataXchgOutput / give to upper layer - DataXCHG dataRcv = { Names::FindName(NodeList::GetNode(srcNodeId)), - Names::FindName(socket->GetNode ()), - val, - stoll(val_time) - }; - dataXchgOutput.push_back(dataRcv); +// DataXCHG dataRcv = { Names::FindName(NodeList::GetNode(srcNodeId)), +// Names::FindName(socket->GetNode ()), +// val, +// stoll(val_time) +// }; +// dataXchgOutput.push_back(dataRcv); ofstream filePacketsSent; filePacketsSent.open("packets_rec.pkt", std::ios_base::app); filePacketsSent << "time: " << Simulator::Now ().GetMilliSeconds () << " by nodeName: " << Names::FindName(socket->GetNode ()) << " dstNodeId: " << socket->GetNode()->GetId() - << " srcNodeId: " << srcNodeId - << " Payload: " << recMessage; +// << " srcNodeId: " << srcNodeId + << " Payload: " << recMessage << std::endl; filePacketsSent.close(); } @@ -115,7 +117,7 @@ NS3Netsim::NS3Netsim(): // LogComponentEnable("LrWpanNetDevice", LOG_LEVEL_ALL); // LogComponentEnable("LrWpanMac", LOG_LEVEL_ALL); // LogComponentEnable("SmartgridDefaultSimulatorImpl", LOG_LEVEL_ALL); - LogComponentEnable("SmartgridNs3Main", LOG_LEVEL_ALL); +// LogComponentEnable("SmartgridNs3Main", LOG_LEVEL_ALL); // LogComponentEnable ("MultiClientTcpServer", LOG_LEVEL_ALL); // LogComponentEnable ("TcpClient", LOG_LEVEL_ALL); // LogComponentEnable ("Socket", LOG_LEVEL_ALL); @@ -296,37 +298,64 @@ NS3Netsim::init (string f_adjmat, // Create the LR-WPAN connections specified in the files with 6LoWPAN // Iterate through the keys found in the network, the keys act as the center of the PAN for (auto center = panNetworks.begin(); center != panNetworks.end(); center++) { - // Stores the nodes in the PAN + // Stores the nodes in the PAN NodeContainer panNodes; // Add the center to the list - panNodes.Add(Names::Find((*center).first)); +// panNodes.Add(Names::Find((*center).first)); for (auto spokes = (*center).second.begin(); spokes != (*center).second.end(); spokes++) { // Add the spokes to the list panNodes.Add(Names::Find(*spokes)); } - // Install the LR-WPAN devices - NetDeviceContainer lrwpanDevices = lrWpanHelper.Install(panNodes); - // Fake PAN association and short address assignment. - lrWpanHelper.AssociateToPan (lrwpanDevices, stoi((*center).first)); - // Add Sixlowpan devices - NetDeviceContainer sixlowpanDevices = sixlowpan.Install (lrwpanDevices); - // Add the ipv6 addresses - Ipv6InterfaceContainer deviceInterfaces = ipv6Address.Assign (sixlowpanDevices); + + WifiHelper wifi; + NetDeviceContainer staDevs; + NetDeviceContainer apDevs; + WifiMacHelper wifiMac; + YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default (); + YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default (); + wifiPhy.SetChannel (wifiChannel.Create ()); + Ssid ssid = Ssid ((*center).first); + wifi.SetRemoteStationManager ("ns3::ArfWifiManager"); + + wifiMac.SetType ("ns3::StaWifiMac", + "ActiveProbing", BooleanValue (true), + "Ssid", SsidValue (ssid)); + staDevs = wifi.Install (wifiPhy, wifiMac, panNodes); + // setup ap. + wifiMac.SetType ("ns3::ApWifiMac", + "Ssid", SsidValue (ssid)); + apDevs = wifi.Install (wifiPhy, wifiMac, Names::Find((*center).first)); + + wifiPhy.EnablePcap ("AccessPoint", apDevs); + wifiPhy.EnablePcap ("Station", staDevs); + + ipv6Address.Assign (staDevs); + ipv6Address.Assign (apDevs); ipv6Address.NewNetwork(); - } - if (verbose > 1) { - cout << "Printing LR-WPAN network connections read from file" << endl; - for (auto it = panNetworks.begin(); it != panNetworks.end(); it++) { - cout << (*it).first << ";"; - for (auto it2 = (*it).second.begin(); it2 != (*it).second.end(); it2++) { - cout << *it2 << ","; - create((*it).first, *it2); - } - cout << endl; - } +// // Install the LR-WPAN devices +// NetDeviceContainer lrwpanDevices = lrWpanHelper.Install(panNodes); +// // Fake PAN association and short address assignment. +// lrWpanHelper.AssociateToPan (lrwpanDevices, stoi((*center).first)); +// // Add Sixlowpan devices +// NetDeviceContainer sixlowpanDevices = sixlowpan.Install (lrwpanDevices); +// // Add the ipv6 addresses +// ipv6Address.Assign (sixlowpanDevices); +// ipv6Address.NewNetwork(); } +// if (verbose > 1) { +// cout << "Printing LR-WPAN network connections read from file" << endl; +// for (auto it = panNetworks.begin(); it != panNetworks.end(); it++) { +// cout << (*it).first << ";"; +// for (auto it2 = (*it).second.begin(); it2 != (*it).second.end(); it2++) { +// cout << *it2 << ","; +// create((*it).first, *it2); +// } +// cout << endl; +// } +// } + //--- set link error rate Ptr em = CreateObject (); em->SetAttribute ("ErrorRate", DoubleValue (stod(LinkErrorRate))); From 1f0fcdb277034c94830adc47566f624283f7cf12 Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Wed, 15 Jul 2020 19:55:50 -0600 Subject: [PATCH 03/22] Wi-Fi seems to be working. Some issues need to be solved. -Wi-Fi seems to be working -The servers need to be modified so that they can use multiple ipv4 addresses. One for WiFi and one for non-wifi. The packets are being delivered right not, but the non-wifi addresses if being used. This needs to be fixed. -Routing for the WiFi network needs to be setup, this will be done using OSLR. -Better file structures need creation for the wifi-network. --- NS3Mosaik/NS3MosaikSim | Bin 1928976 -> 1933360 bytes NS3Mosaik/mosaik_api/include/NS3Netsim.h | 5 +- NS3Mosaik/mosaik_api/include/ns3-helper.h | 28 ++- NS3Mosaik/mosaik_api/src/NS3Netsim.cpp | 223 ++++++++---------- NS3Mosaik/mosaik_api/src/ns3-helper.cpp | 9 - .../data/IEEE13Node-adjacency_matrix.txt | 34 +-- .../data/IEEE13Node_AppConnections_Tap.csv | 2 + .../tapcontrol/data/IEEE13Node_BusXY.csv | 2 + .../data/IEEE13Nodeckt_Actives_Tap.csv | 2 + 9 files changed, 140 insertions(+), 165 deletions(-) diff --git a/NS3Mosaik/NS3MosaikSim b/NS3Mosaik/NS3MosaikSim index 81aea98c62499bbd5a2eeba11eadb9666b0522ac..49ebc33995dae9cae90af7b510a45a887a640252 100755 GIT binary patch delta 139070 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 z ze16i{it56W`S~SfY{YNyGPmn#EmF^!70tq4A~ZNF z4VtSsre@n?K@U(EzC2l;9w%`9;bV$%_9=zs)%Y#Nw7G@l<;A5Vi%TnutLy_)X5IW@ z$}ttJ{yQzvH9x_jHzox42AH4Z_#dt;#LjsF!sfBDUM_!?$Q5uL_@Q|MUskSD#1 zRS%>S*`3NY_l~yeiK%{Uf(z}b7ftBShPhC8J!FJ8yU>Xa z&_A0Qq4&GZolSJ3W|k95NtgJEg{2FNOBQ96fU3u5WusyTWL4fiAcI{cw09Io*ke)4 zLcMYQ^NVZ76_-`i6zA9QFMrA}X|l~fYw?DbhyM@ym1Dq%*e*~nAEh1#x-W;4GB`*-!EeRb3HL9ES-2I#-U zPPL34FsizuTy$|@VfBQp@|uJJpv7LkATz+5cJ&@V@rI^ZtuO7;35Kw`xQ6{_0Hy3% zKWb$?JAv6>?o1`8hUx)d8q5xkhN}96z&PDAtS4&>qKWKE2n}c1R@%eo zX4R+Z<`IGH!x^+Q+JbJ*o}>p%31Wd^)SrcQp&{%CZ|Y43RKurG*{Lotvum=tu*$BW zx?hrl^%4CNU1Op1tuyHaH*QsLccC`47R}y2XXd=(qM8wfMKu*wi!<^Iv-0hZj110o zwF^yR>q2Rc-ZQ!vv-r>yy*YY}e$SW!wx%nM(p~Zb^?7-IH<>I>T-{z6&aP7$z^a45 z{~QgYz4SiAyRsvLp|Kab(xCNW;6FZ1qx~PA(MfNeMOb7IFdw$j5ndhcB0Y|M)Qxsw z1?}J+(!*#JBiCTG$C|(q26clGf!WCCWg>gwf;OCe?nCp~nh3g--T%9m$(q7wH$7#z zU4K8lr@m?I?QB9kjnRM3Agp(9YS*okz4Re7V%Px-sP6AG+Cn!pMg7_^3v2B~!&vq- zstHA1?FC(!(XMr3-J+<4b?F5yITcO2c;ajkBg9%Kf|Qm>>dRV&f>}NkK|ORfcdqyN ztecDlEG!sYYHNNN4uu{&k_tn~iUv25*M;8BVkzCpD!$h8C>q*CG5rz^N0&Qyv6zMW zV}mvJO$PX)rWhK{7Hf1EyY~+*mled)P(5&H5bM^D=CIrW)Qzcew4YD*4JVv#*Hb2R zVL9FCAYVsm$;={0QT0McNqI>PTh@=}>TX3TEFzYg*C#-a98)OioG_`Xq^7uvwSx0! z!AaCNfVV3tyJXQsFq?`hbYpDb5AYsF>_~TZ4OfqXBx+)P;$Z^RB*JWiiBZKpSVJOM zdq^S;?>YMaaN-GRRmJeNUC>eVjATBcS!Pv8D{#lg%4Lz4hV!guBfi32VaZ zL!jV}7+MA2WY?Cm>py74tR;;m>OQlBS#uh2fJOTGIZZ!yaRzt=kQQjVW$8m5Z_1=Y zSavAw%-$bOHLgK>fAKltB4HUg`OuF459QjEz=hxRQD*+>=3Cr%)c@|jnNOS6PXr7} zS+I~*XH!iNc9r@>V0E5VT8#FbWsgr=2wyxdn=q>~t+b@Lyhd?2DyvG$ zYi2u&=FYz{eEnkvU?O9|A!iqgDqOuqEk-76#D0V0+@if+_@O|!C2<7l@4@b^V!l{ad} z75iik9j&`g>&q)+F=MGGOPoT@7O7SzjiXm{s$M+To5TT{Ug zozC~t2WJJlq}kcD=~QFyO`$X?ME3>XY|5fN*uA-6;n@RdC*7^2o1Q$ui#=FC zgZ0iu1N8lqy_w5xFcsXcX_+n%Bs8Z}{jM}KTQ(JjYDX&3#|<9KwmT@*CycbPx*4#J zS!Y1&hB;uun2V_v1x~EPDI3P+q=iJVsqu>|S^d{qqKgQ%2LJC?^bbxpV<^nq#u?Bx z%Vqe4O8sdq3!IA^JN%P2i8cPJ^=01EXqtX+zY(5}@nh2*8QJL$hh8vXhd+*J<>DJ7 zY9GK>|DyHPKaTZ;kSI=HJ0qB7UC~UY@;l0Iu^zVRH*Gcx_*>I%@{6;Fh1$$KL!>*|`)NH>caKRZm>8h5)>i^cJu}yxot1Cut)7rJ^Y+O7H?v*iC=KGu0 z89jqH8g~t|PNaR@(s5xP*b1HU`$h9*!$PPBdoF?wWEZYz`E2`jEnoL33}LD9;D5i( zpv&3yLYhvBN-L_1Szj19w#^m1ncfM^a7$b$y9j~28BGsn*DQ!M!I}!IYFNo-t(Kk3 zpxI*42+5$~fyNSJ&#!@LIEP1r%$!2UAx{(w9Z!3NK#+9P=sRXsS4)9s&cliWVR0f$ z9tx&He5k)(oa10$c+eR3rXMsG_Xc7ApFlk^y?A!v!qOU+9Y^C>*q_p7njds*;Bwto*Yiy`Kl6lUE82v92u$iOtP{; zK`<*er9(d)USg zVKII*phtP(tv04qR}{@JuDM~I;BR#AQK5Qpo=M+2+E1^{a$^I!QutO;D5#;?42#}h zVX%NU*ytb;2tAez%BTwmY6B8r4>w--pEZaL82}54+8qMqCOgsl^z~qmc7tH+yKZ0= zi|t`-M|Ut3h?wfwix*(y$%CcqXSKPES|IjJObFH^`}#9;C|#;=arm=4yHj6MjON2` zjB}ei&D38kjAyHRfWbAULjVH%l{oZ4y=nj4nyReqe1|>Wh*#vs3?oVXS}xdrFY4_t zO)e?Fx?~o&w+t5E6J%7z(BTX`+8~VHQq)9!TWSQ`9!0G_vcv!^k-;h<@?x{1VQ?-^ zq@iM08#^t8eT*m=_Ed;ZBlUfKQ}tJp!r96`5GN+|f$%eKR39FwpX*L%;UX}eJ=PP( z4&puCH#vkYj)iD=Y?`~}-XGq&`u;&SH;AuhG1{N@(bGpyVV!>m*Dx#s)KM@#-ZQ@@p|ql?u(UXh zrThv96;rNgUMx2lf}NI(Fn!txFa3}45v(!^JX*Eg%D%x+?^pr^o}?&Fgwq&!>a&uA z0F%IK`@~wqy`Yi6KG8 znZtpp)cfHfS*-jbY|;7Q!4v&qJKmCt27x{|<)YR@FPs3Fnfn z)bQ5-W_KAZY78B$j%Il-G^A7i%;K7idCc4mobc7*)S)+}2J5k@9&Fzb*gQc@+6Olc ztJuLT8WS#p#W;*3v&v^zRF(04eMV_<8ANEjdp$?NhICRkH28Eh1fOR!AsV|pr8l}% zGmFm#H-yF>AYy`!T?#L{as-{k>hnO+cT5Mz1t(E6*!WDEt@od1W&?8}R%;lUdh|aLC}&v4k}%d1QCzlH7y1AekL|}G##kVo$JHy8VBpe*<9dg%7X%< zbHQ|q(gFAAXd2}j7dMXObb;^UULOHbr=EIVqLtej z{HSd9fyFg+0v&)$zs6RKpeFe6H0*R7{k!UV0bi!1YlY=&D61F&mj8VqENQuuA)?zf z)}qIbb!R(bVP(jKrQqQtGjo|r1HAar4Z27OF&9M9B$zjMvL~m4N^opgl9ihD>1kg2 z;gkSMDrKZ&`?#qYzwNWM5y`+|fm>qyW~7^xNnRy>zYz8#fb7CaVx!@4Sh0 zQ~=*^-CBD0x?*~l3UA`O?KaJ!HdTF@+2_)JX5-5N2CQTY0PSzQnQuV&pun!VG{$Va znQy>f*(G52G+xYaEN4+AG{J0qP{4p~Y(WWBW_)+RfQ#795?ZSkF#9~(&!esp&wLf7 zj+M-#iROkzey12Pm+b^Df8*VK0|vqQ&paCAX}r7tXDExB55?s}Y{tWE1r}B{A39*X zvTwk*+0OaUGUJVX0~WAL^J%Px@9RV2@9hKZE^awaS+g^M<(5*Dr}6e%%LX>DlqPr@ zFYW)ifjtlR)Oh(r*(i$RSH?S%e#SR|naZfiY`nYQ@|0j}VD>U-nepm=!Lzb0Y(W`~ z^){Xg!{;)%jOH>L?jf6$je!3r182tT*Eh(qbo~DaJ=#$IY Qu5y~-vg>yCLphE3e`=_pHUIzs delta 129733 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 Oku~DB0EG35r2hkfarZp{ diff --git a/NS3Mosaik/mosaik_api/include/NS3Netsim.h b/NS3Mosaik/mosaik_api/include/NS3Netsim.h index 6e0c483..929b27b 100644 --- a/NS3Mosaik/mosaik_api/include/NS3Netsim.h +++ b/NS3Mosaik/mosaik_api/include/NS3Netsim.h @@ -63,8 +63,7 @@ struct DataXCHG { static vector dataXchgInput; ///< Input data exchange vector static vector dataXchgOutput; ///< Output data exchange vector static map mapIpv4NodeId; ///< Map from client Ipv4 to Node Id -static map> panNetworks; - +static map> wifiNetworks; ///< Map for the end-node in the primary network and the secondary network nodes class NS3Netsim { public: @@ -206,7 +205,7 @@ class NS3Netsim { * \param tcpOrUdp a string that is either set to tcp or udp, indicating which kind of server will be created * \param server holds the server id */ - void setUpServer(InetSocketAddress addressIpv4, Inet6SocketAddress addressIpv6, string protocol, string server); + void setUpServer(InetSocketAddress addressIpv4, string protocol, string server); /** * Sets up a tcp or udp client depending on what has been passed in diff --git a/NS3Mosaik/mosaik_api/include/ns3-helper.h b/NS3Mosaik/mosaik_api/include/ns3-helper.h index 63e44ea..29926bc 100644 --- a/NS3Mosaik/mosaik_api/include/ns3-helper.h +++ b/NS3Mosaik/mosaik_api/include/ns3-helper.h @@ -115,12 +115,28 @@ void PrintIpAddresses(NodeContainer nodes); map CreateMapIpv4NodeId(NodeContainer nodes); /** - * TODO: Reads the files for the LR-WPAN networks that will be created. - * For now returns a fake network to test the LR-WPAN connections - * - * \param lrWpanFileName String, filename of the file that contains information on the LR-WPAN networks - * \returns Map, keys being the center of LR-WPAN and set of nodes being the to that key + * Get a wifi net-device from the node passed in */ -map> CreateMapForLRWPAN(string lrWpanFileName); +template +Ptr GetNetDeviceOfType(NodeContainer node) { + // Get the number of nodes in the node container, if larger than one, throw an error + if (node.GetN() != 1) { + throw "Number of nodes passed in is too large, the node container can only contain one node."; + } + + // Now iterate through the net devices + for (int i = 0; i < node.Get(0)->GetNDevices(); i++) { + // Try a dynamic cast + Ptr netDevice = DynamicCast (node.Get(0)->GetDevice(i)); + // If T is not null, successful, return the device + if (netDevice != 0) { + return netDevice; + } + } + + // If you've gotten to this point there is no net device of this type, throw an error + throw "NetDevice of this correct type not found"; +} + #endif /* SMARTGRID_NS3_HELPER_H_ */ diff --git a/NS3Mosaik/mosaik_api/src/NS3Netsim.cpp b/NS3Mosaik/mosaik_api/src/NS3Netsim.cpp index 74a7053..b42ef2e 100644 --- a/NS3Mosaik/mosaik_api/src/NS3Netsim.cpp +++ b/NS3Mosaik/mosaik_api/src/NS3Netsim.cpp @@ -30,11 +30,9 @@ #include #include #include -#include "ns3/lr-wpan-module.h" #include "ns3/core-module.h" #include "ns3/internet-apps-module.h" #include "ns3/wifi-module.h" -#include "ns3/sixlowpan-module.h" #include "ns3/smartgrid-default-simulator-impl.h" #include "NS3Netsim.h" #include "ns3-helper.h" @@ -64,16 +62,17 @@ ExtractInformationFromPacketAndSendToUpperLayer (Ptr socket) string recMessage = string((char*)buffer); recMessage = recMessage.substr (0,packet->GetSize()); - // TODO: Change this so that we get ipv6 and ipv4 addresses depending on the socket passed in -// Ipv4Address srcIpv4Address = InetSocketAddress::ConvertFrom (from).GetIpv4(); -// uint32_t srcNodeId = mapIpv4NodeId[srcIpv4Address]; + Ipv4Address srcIpv4Address = InetSocketAddress::ConvertFrom (from).GetIpv4(); + uint32_t srcNodeId = mapIpv4NodeId[srcIpv4Address]; //--- print received msg NS_LOG_DEBUG( "Pkt Rcv at " << Simulator::Now ().GetMilliSeconds () - << " by nodeName: " << Names::FindName(socket->GetNode ()) + << " dstNodeName: " << Names::FindName(socket->GetNode ()) << " dstNodeId: " << socket->GetNode()->GetId() -// << " srcNodeId: " << srcNodeId + << " srcNodeName: " << Names::FindName(socket->GetNode ()) + << " srcNodeId: " << srcNodeId + << " from: " << InetSocketAddress::ConvertFrom (from).GetIpv4() << " Size: " << packet->GetSize() << " Payload: " << recMessage << endl; @@ -86,20 +85,24 @@ ExtractInformationFromPacketAndSendToUpperLayer (Ptr socket) string val_time = recMessage.substr(current+1); //--- insert data on dataXchgOutput / give to upper layer -// DataXCHG dataRcv = { Names::FindName(NodeList::GetNode(srcNodeId)), -// Names::FindName(socket->GetNode ()), -// val, -// stoll(val_time) -// }; -// dataXchgOutput.push_back(dataRcv); + DataXCHG dataRcv = { Names::FindName(NodeList::GetNode(srcNodeId)), + Names::FindName(socket->GetNode ()), + val, + stoll(val_time) + }; + dataXchgOutput.push_back(dataRcv); ofstream filePacketsSent; filePacketsSent.open("packets_rec.pkt", std::ios_base::app); - filePacketsSent << "time: " << Simulator::Now ().GetMilliSeconds () - << " by nodeName: " << Names::FindName(socket->GetNode ()) - << " dstNodeId: " << socket->GetNode()->GetId() -// << " srcNodeId: " << srcNodeId - << " Payload: " << recMessage << std::endl; + filePacketsSent << "Pkt Rcv at " << Simulator::Now ().GetMilliSeconds () + << " dstNodeName: " << Names::FindName(socket->GetNode ()) + << " dstNodeId: " << socket->GetNode()->GetId() + << " srcNodeId: " << srcNodeId + << " from: " << InetSocketAddress::ConvertFrom (from).GetIpv4() + << " Size: " << packet->GetSize() + << " Payload: " << recMessage + << endl; + filePacketsSent.close(); } @@ -109,29 +112,7 @@ NS3Netsim::NS3Netsim(): //--- setup simulation type GlobalValue::Bind ("SimulatorImplementationType", StringValue ("ns3::SmartgridDefaultSimulatorImpl")); -// LogComponentEnable ("Ping6Application", LOG_LEVEL_ALL); -// LogComponentEnable("ArpL3Protocol", LOG_LEVEL_ALL); -// LogComponentEnable("ArpCache", LOG_LEVEL_ALL); -// LogComponentEnable("Simulator", LOG_LEVEL_ALL); -// LogComponentEnable("LrWpanCsmaCa", LOG_LEVEL_ALL); -// LogComponentEnable("LrWpanNetDevice", LOG_LEVEL_ALL); -// LogComponentEnable("LrWpanMac", LOG_LEVEL_ALL); -// LogComponentEnable("SmartgridDefaultSimulatorImpl", LOG_LEVEL_ALL); -// LogComponentEnable("SmartgridNs3Main", LOG_LEVEL_ALL); -// LogComponentEnable ("MultiClientTcpServer", LOG_LEVEL_ALL); -// LogComponentEnable ("TcpClient", LOG_LEVEL_ALL); -// LogComponentEnable ("Socket", LOG_LEVEL_ALL); -// LogComponentEnable ("SocketFactory", LOG_LEVEL_ALL); -// LogComponentEnable ("TcpSocket", LOG_LEVEL_ALL); -// LogComponentEnable ("TcpSocketBase", LOG_LEVEL_ALL); -// LogComponentEnable ("SixLowPanNetDevice", LOG_LEVEL_ALL); -// LogComponentEnable ("TcpL4Protocol", LOG_LEVEL_ALL); -// LogComponentEnable ("IpL4Protocol", LOG_LEVEL_ALL); -// LogComponentEnable ("EventImpl", LOG_LEVEL_ALL); -// LogComponentEnable ("Node", LOG_LEVEL_ALL); -// LogComponentEnable ("Application", LOG_LEVEL_ALL); -// LogComponentEnable ("Packet", LOG_LEVEL_ALL); -// LogComponentEnable ("Address", LOG_LEVEL_ALL); + LogComponentEnable ("SmartgridNs3Main", LOG_LEVEL_ALL); } @@ -154,18 +135,26 @@ NS3Netsim::init (string f_adjmat, { // Point to point helper for point to point connections PointToPointHelper pointToPoint; - // LrWpanHelper for 802.15.4 wireless communcation - LrWpanHelper lrWpanHelper; // Internet stack helper to help with installation of internet InternetStackHelper internet; // Pointer to Ipv4 Internet helper class Ipv4AddressHelper ipv4Address; - // Pointer to the Ipv6 Internet helper class - Ipv6AddressHelper ipv6Address; // Pointer to mobility (position) helper class MobilityHelper mobility; - // Helper, set up a stack to be used between IPv6 and a generic - SixLowPanHelper sixlowpan; + // Wifi network helper, meant to help install the wifi net device + WifiHelper wifi; + wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager"); + // Wifi mac helper + WifiMacHelper wifiMac; + // Wifi physical layer helper + YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default(); + // Wifi channel helper + YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default(); + // Set the properties of the wifi channel + wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel"); + wifiChannel.AddPropagationLoss ("ns3::LogDistancePropagationLossModel", + "Exponent", DoubleValue (3.0), + "ReferenceLoss", DoubleValue (40.0459)); allApplications = ApplicationContainer (); //--- verbose level @@ -186,9 +175,8 @@ NS3Netsim::init (string f_adjmat, linkCount = 0; //--- set address properties for ipv4 - ipv4Address.SetBase ("10.0.0.0", "255.255.255.252"); - //--- set the address properties for ipv6 - ipv6Address.SetBase (Ipv6Address ("2001:2::"), Ipv6Prefix (64)); + // For the primary network, the address will start with 172 + ipv4Address.SetBase ("172.0.0.0", "255.255.255.0"); //--- set application destination port sinkPort = 3030; @@ -212,6 +200,7 @@ NS3Netsim::init (string f_adjmat, NS_LOG_INFO ("Load node names and coordinates"); arrayNamesCoords = ReadCoordinatesFile (nodeCoordinatesFilename); arrayNodeCoords = loadNodeCoords(arrayNamesCoords); + PrintNamesCoordinates (nodeCoordinatesFilename.c_str (), arrayNamesCoords); if (verbose > 1) { PrintNamesCoordinates (nodeCoordinatesFilename.c_str (), arrayNamesCoords); } @@ -263,7 +252,8 @@ NS3Netsim::init (string f_adjmat, internet.Install (NodeContainer::GetGlobal ()); //--- create network topology - NS_LOG_INFO ("Create p2p and lr-wpan links Between Nodes, then set internet stack and addresses"); + NS_LOG_INFO ("Create p2p links and wifi networks between Nodes, then set internet stack and addresses"); + // Create the p2p links for the hard-wired links pointToPoint.SetDeviceAttribute ("DataRate", StringValue (LinkRate)); pointToPoint.SetChannelAttribute ("Delay", StringValue (LinkDelay)); for (size_t i = 0; i < nodeAdjMatrix.size (); i++) @@ -292,69 +282,40 @@ NS3Netsim::init (string f_adjmat, } } - // Getting PAN network from files - panNetworks = CreateMapForLRWPAN(""); - - // Create the LR-WPAN connections specified in the files with 6LoWPAN - // Iterate through the keys found in the network, the keys act as the center of the PAN - for (auto center = panNetworks.begin(); center != panNetworks.end(); center++) { - // Stores the nodes in the PAN - NodeContainer panNodes; - // Add the center to the list -// panNodes.Add(Names::Find((*center).first)); - for (auto spokes = (*center).second.begin(); spokes != (*center).second.end(); spokes++) { - // Add the spokes to the list - panNodes.Add(Names::Find(*spokes)); - } + // For the wifi network, the address will start with 10 + ipv4Address.NewNetwork(); + ipv4Address.SetBase ("192.168.0.0", "255.255.255.0"); + wifiNetworks["632"] = set(); + wifiNetworks["632"].insert("6321"); + wifiNetworks["632"].insert("6322"); + // Create a WiFi network according to the nodes passed in, each set inside the vector is a network that needs to be created + for (auto network = wifiNetworks.begin(); network != wifiNetworks.end(); network++) { + // Grab the end node of the primary network + string primaryNodeName = (*network).first; + + // Find all the nodes in the network + NodeContainer networkNodes; + networkNodes.Add(Names::Find(primaryNodeName)); + for (auto nodeName = (*network).second.begin(); nodeName != (*network).second.end(); nodeName++) { + networkNodes.Add(Names::Find(*nodeName)); + } - WifiHelper wifi; - NetDeviceContainer staDevs; - NetDeviceContainer apDevs; - WifiMacHelper wifiMac; - YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default (); - YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default (); - wifiPhy.SetChannel (wifiChannel.Create ()); - Ssid ssid = Ssid ((*center).first); - wifi.SetRemoteStationManager ("ns3::ArfWifiManager"); - - wifiMac.SetType ("ns3::StaWifiMac", - "ActiveProbing", BooleanValue (true), - "Ssid", SsidValue (ssid)); - staDevs = wifi.Install (wifiPhy, wifiMac, panNodes); - // setup ap. - wifiMac.SetType ("ns3::ApWifiMac", - "Ssid", SsidValue (ssid)); - apDevs = wifi.Install (wifiPhy, wifiMac, Names::Find((*center).first)); - - wifiPhy.EnablePcap ("AccessPoint", apDevs); - wifiPhy.EnablePcap ("Station", staDevs); - - ipv6Address.Assign (staDevs); - ipv6Address.Assign (apDevs); - ipv6Address.NewNetwork(); - -// // Install the LR-WPAN devices -// NetDeviceContainer lrwpanDevices = lrWpanHelper.Install(panNodes); -// // Fake PAN association and short address assignment. -// lrWpanHelper.AssociateToPan (lrwpanDevices, stoi((*center).first)); -// // Add Sixlowpan devices -// NetDeviceContainer sixlowpanDevices = sixlowpan.Install (lrwpanDevices); -// // Add the ipv6 addresses -// ipv6Address.Assign (sixlowpanDevices); -// ipv6Address.NewNetwork(); - } + // Create a new channel for a new wi-fi network + wifiPhy.SetChannel(wifiChannel.Create()); + // New ssid with the name of the end node in the primary network + Ssid ssid = Ssid(primaryNodeName); -// if (verbose > 1) { -// cout << "Printing LR-WPAN network connections read from file" << endl; -// for (auto it = panNetworks.begin(); it != panNetworks.end(); it++) { -// cout << (*it).first << ";"; -// for (auto it2 = (*it).second.begin(); it2 != (*it).second.end(); it2++) { -// cout << *it2 << ","; -// create((*it).first, *it2); -// } -// cout << endl; -// } -// } + // Set the type of mac network, with the correct ssid + wifiMac.SetType("ns3::AdhocWifiMac", + "Ssid", SsidValue(ssid)); + + // Connect all the devices + NetDeviceContainer devices = wifi.Install (wifiPhy, wifiMac, networkNodes); + + // Assign the addresses + ipv4Address.Assign(devices); + ipv4Address.NewNetwork(); + } //--- set link error rate Ptr em = CreateObject (); @@ -386,13 +347,10 @@ NS3Netsim::init (string f_adjmat, NS_LOG_INFO ("Number of all nodes is: " << nodes.GetN ()); //--- set regular trace file - AsciiTraceHelper ascii; +// AsciiTraceHelper ascii; // pointToPoint.EnableAsciiAll (ascii.CreateFileStream ("pointToPointNS3.tr")); -// lrWpanHelper.EnableAsciiAll (ascii.CreateFileStream ("lrWpanHelperNS3.tr")); // pointToPoint.EnablePcapAll("pcapNS3Netsim.pcap"); // pointToPoint.EnablePcap("dse", 0, 0, true); -// lrWpanHelper.EnablePcapAll("lrWpanHelperNS3.pcap"); -// lrWpanHelper.EnablePcap("dse", 0, 0, true); } @@ -401,7 +359,6 @@ NS3Netsim::create (string client, string server) { NS_LOG_FUNCTION(this); bool found = false; - //--- //--- update list of application connections //--- @@ -419,10 +376,10 @@ NS3Netsim::create (string client, string server) break; } } + //--- new connection, create entries if(found == false) { arrayAppConnections.push_back(record); - // create server socket NS_LOG_INFO("Create server."); Ptr srvNode = Names::Find(server); @@ -442,22 +399,25 @@ NS3Netsim::create (string client, string server) } // create client socket NS_LOG_INFO("Create client."); - // Check if this is part of one of the LR-WPAN networks - // If part of LR-WPAN, use ipv6, otherwise use ipv4 - if (panNetworks.count(server) != 0 && panNetworks[server].count(client) != 0) { - Ipv6InterfaceAddress sink_iaddr = dstNode->GetObject()->GetAddress(1,0); - Inet6SocketAddress remote = Inet6SocketAddress(sink_iaddr.GetAddress(), sinkPort); - setUpClient(AddressValue(remote), tcpOrUdp, server, client); + + // Get the net device depending on if the nodes are in a wifi network or a p2p network + Ipv4InterfaceAddress serverAddr; + + if (wifiNetworks.count(server) != 0 && wifiNetworks[server].count(client) != 0) { + std::cout << "here" << std::endl; + serverAddr = dstNode->GetObject()->GetAddress(2,0); } else { - Ipv4InterfaceAddress sink_iaddr = dstNode->GetObject()->GetAddress(1,0); - InetSocketAddress remote = InetSocketAddress(sink_iaddr.GetLocal(), sinkPort); - setUpClient(AddressValue(remote), tcpOrUdp, server, client); + serverAddr = dstNode->GetObject()->GetAddress(2,0); } + + InetSocketAddress remote = InetSocketAddress(serverAddr.GetLocal(), sinkPort); + std::cout << remote.GetIpv4() << std::endl; + setUpClient(AddressValue(remote), tcpOrUdp, server, client); } } void -NS3Netsim::setUpServer(InetSocketAddress addressIpv4, Inet6SocketAddress addressIpv6, string protocol, string server) +NS3Netsim::setUpServer(std::vector addressIpv4, string protocol, string server) { NS_LOG_FUNCTION(this); // Where the returned application will be stored @@ -586,9 +546,10 @@ NS3Netsim::runUntil (string nextStop) } } - if (stoi(nextStop) % 100 == 0){ - schedule ("6321", "632", to_string(-stoi(nextStop)), to_string(stoi(nextStop) + 20)); - } +// if (stoi(nextStop) % 100 == 0){ +// schedule ("6321", "632", to_string(-stoi(nextStop)), to_string(stoi(nextStop) + 20)); +// schedule ("6322", "632", to_string(-stoi(nextStop)), to_string(stoi(nextStop) + 20)); +// } if (verbose > 1) { std::cout << "NS3Netsim::runUntil After_run NS3 time: " << Simulator::Now ().GetMilliSeconds () << std::endl; diff --git a/NS3Mosaik/mosaik_api/src/ns3-helper.cpp b/NS3Mosaik/mosaik_api/src/ns3-helper.cpp index 6698597..d52d8e0 100644 --- a/NS3Mosaik/mosaik_api/src/ns3-helper.cpp +++ b/NS3Mosaik/mosaik_api/src/ns3-helper.cpp @@ -266,12 +266,3 @@ CreateMapIpv4NodeId(NodeContainer nodes) return mapIpv4NodeId; } - -map> CreateMapForLRWPAN(string lrWpanFileName) { - // What will be returned - map> readFromFile; - readFromFile["632"] = set(); - readFromFile["632"].insert("6321"); - readFromFile["632"].insert("6322"); - return readFromFile; -} \ No newline at end of file diff --git a/TapControl/tapcontrol/data/IEEE13Node-adjacency_matrix.txt b/TapControl/tapcontrol/data/IEEE13Node-adjacency_matrix.txt index 86394ae..198f26d 100644 --- a/TapControl/tapcontrol/data/IEEE13Node-adjacency_matrix.txt +++ b/TapControl/tapcontrol/data/IEEE13Node-adjacency_matrix.txt @@ -1,16 +1,18 @@ -0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 -0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 -0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 -0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 -0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file diff --git a/TapControl/tapcontrol/data/IEEE13Node_AppConnections_Tap.csv b/TapControl/tapcontrol/data/IEEE13Node_AppConnections_Tap.csv index b0f925a..febdb69 100644 --- a/TapControl/tapcontrol/data/IEEE13Node_AppConnections_Tap.csv +++ b/TapControl/tapcontrol/data/IEEE13Node_AppConnections_Tap.csv @@ -1,2 +1,4 @@ 611,632,sensing 632,650,acting +6321,632,sensing +6322,632,sensing \ No newline at end of file diff --git a/TapControl/tapcontrol/data/IEEE13Node_BusXY.csv b/TapControl/tapcontrol/data/IEEE13Node_BusXY.csv index ba14e1e..e31d240 100644 --- a/TapControl/tapcontrol/data/IEEE13Node_BusXY.csv +++ b/TapControl/tapcontrol/data/IEEE13Node_BusXY.csv @@ -14,3 +14,5 @@ RG60, 200, 300 675, 400, 100 652, 100, 0 680, 200, 0 +6321, 201, 251 +6322, 201, 251 \ No newline at end of file diff --git a/TapControl/tapcontrol/data/IEEE13Nodeckt_Actives_Tap.csv b/TapControl/tapcontrol/data/IEEE13Nodeckt_Actives_Tap.csv index 3cd68a8..c5c66f6 100644 --- a/TapControl/tapcontrol/data/IEEE13Nodeckt_Actives_Tap.csv +++ b/TapControl/tapcontrol/data/IEEE13Nodeckt_Actives_Tap.csv @@ -1,4 +1,6 @@ Sensor_611,getV,Line.684611,BUS2,PHASE_3 +Sensor_6321,getV,Line.684611,BUS2,PHASE_3 +Sensor_6322,getV,Line.684611,BUS2,PHASE_3 Actuator_650,setTap,Transformer.REG3,BUS1,PHASE_3 Prober_611-V3,getV,Line.684611,BUS2,PHASE_3 Prober_650-T3,getTap,Transformer.REG3,BUS1,PHASE_3 From debc4d83578dcfc140372762cbc22bf3fc2fd1bd Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Thu, 16 Jul 2020 16:52:06 -0600 Subject: [PATCH 04/22] TCP applications ported over. -MultiClientTcpServer and TcpClient have both been changed so that they use use ipv4 only, but MultiClientTcpServer creates 2 sockets, 1 for primary network and one for the wiki network. -Useful helper methods created to make life easier. - NS3Netsim changed so that it now works with the modified TCP application. --- .gitignore | 1 + NS3Mosaik/NS3MosaikSim | Bin 1933360 -> 1937904 bytes NS3Mosaik/mosaik_api/include/NS3Netsim.h | 4 +- NS3Mosaik/mosaik_api/include/ns3-helper.h | 46 +++++++-- NS3Mosaik/mosaik_api/src/NS3Netsim.cpp | 88 ++++++++++-------- NS3Mosaik/mosaik_api/src/ns3-helper.cpp | 24 +++++ .../include/multi-client-tcp-server.h | 34 +++++-- .../src/multi-client-tcp-server.cc | 62 +++++++----- 8 files changed, 178 insertions(+), 81 deletions(-) diff --git a/.gitignore b/.gitignore index c84f27f..3550c7e 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ TapControl/Monitor.png TapControl/Monitor.png NS3Mosaik/NS3MosaikSim NS3Mosaik/NS3MosaikSim +NS3Mosaik/NS3MosaikSim diff --git a/NS3Mosaik/NS3MosaikSim b/NS3Mosaik/NS3MosaikSim index 49ebc33995dae9cae90af7b510a45a887a640252..d71fc8f6f98400463cdd8c5412bf9ed7ffe4cab1 100755 GIT binary patch delta 130189 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

sK^ z!&&)-@Ui?N1^8q6A34CUF^ROtedGYwb>O+F<9qTprDORg9hmkzz}p<)k`9r{0dI1^ zCpzH&`kaRJl~;?%NGjS-zApX>C2K!9sY+~wQO-Gy*~##_4t&BmTB~;`V{9&Sqy?pX zCa1ftX=<<+X`Iofzg*L)_n;<5Jf8I%@wx(IJGh94PPI>S+mQxH?Gdg&A;ED!6W~z$ zssV>?FYKCL$?oue-ZC&VD%mB#aQ8C<=<)zLxWif|_0$zTsa}DQr2SD+I9_L&rtpJ8 zy*}4yXy}p2LTwY)&9*$H*>F6=UDBAM2g>6_?pL=x zLIz>&E+UM24Z`&0Z76*=2rjZWlyV2jPd%13;B@psOpSeXZ?IfTd3asV!1R95GE+~| zGyyO&Fs2_>AA$)|6qDp;h>2F>t1z4(B#$n!tiB=1zFRzaFXau9%LUFng3huZjHrgy z14l~O=ZxsYi0VM7zt*M7L*>A>JV`X%Dl31Y4aV-S=;Ukp-~ID;p5yJ+{Pl$qqm!@Z zKOaGhhRQufK>L}043#tf80uW5s1P+sNpLPB28B?=1n1SFO?BgbYb|=7;M~afuM@s# zuBW>8=z)ArZKMZby*`;4G0qu(6aFsv7s1~Z|DyQ2;a?1Ycl* zlK7Xxzcl_n`1|7ThkqIT{WBuQnUA$KXWzG?0Q80Hu(`#Y&?FgKyE5-vX#t;~(J<5O z?^f&~xM1w5dDJ7*Y!P2SqDh(NrCz7+aBMtS;Yr5U`xJP@+(L}MLj#YPYkB;7+iDw4 zmLA@hzCB`YE$ZE+-;S8eiADFR*imx@@%tSLIchd1c7hiC`P5ieB`$w9Kf6cQI0Rnq z!V2OogcK|qJh}jEX~sUg2W(1MQHHGyLkWxi;UIOuO{=D+Qx)sf~svp6@Y%Us#3Ce!lS1Sp@r_h?d^5%(a(QCT9&ztNO(a0 zC(K=H^uETjFvG9?N)^BAae1!a5XH&Qbr0+0{V`}2)E9}g;)K~hKpUs4lH-iz%(rw^ zt^kHAzc@S5r4#1L)z>ktcaEXTwY$uN5kU&u8pVn&khUd;l(6LSRPm&_iRTCwlrlC> zA79;~5hu<5BJvg`pENg1%(5B+us2QJ%Y1B|JL-=H$m(7O2zB+{mY-gQv*DEI{YLv0 z%;k?4rY-s@iBXMDc}=g6O$$c%{8X)?`z#UuA+W$oql5NDOsV}cE9veM>SF6}mOjm5@f~l z!K@HbMz~tZL)qYm{nEK#KnZoY%vr~>y1uRNnXTOR z0Bc{S+d5V+uRonoCLydKmg)4@yU=~G6jX)lOe=NWR?#1vHv3oT!%l|m{mK?W|E24r zzm1l~xlb{@dP$a_%@((nY#xkIUtXiOKbup!nRMegMtGrT5j)e7C7$>%Lp4N?am$8| zv7vcGFwj{xbchXYTL<{@3Wc08m##`S@-x;P{n2WsOXXmN#B zo-vp05@_SGFE6ASsTH%Kbwltf3!=V;@z@<=)n2;$!*#n{G*B^WTN@OmhF>Jlv*t$1 zIior0sG$j&tw%7m1dRF+s?o(0=8`n-thuyb38w$TRRC6v)T;snzq>-;o<;k2asr(^ zYi^Qg9-FK0|HPLGN+CD)W%gUc^>Ui@0W$W$!1i;SpBi;>0OQki!{a1GwgSplw?;}> zG}ERz#5u-sjD7YaY*F6WqCBIdU(7|ybY*Vadicsh?q*jh?H998nMzD{h5gW$eo;vF zx=QCkmS117QZt;0z4V;fuXHQDMx0a+z-`eru*a@FM>Wowr-)uxX!|*HtdOrzvGe9; zqCx_-J8urGU5=H~*BO0BL-i0YA*1fp2ZbdZ{Dn&cUw!7AkY8x^d3=ba)Mt)CWaZ z|7Tio34PzY>$Kw%B<{OH)=Q9h@Vt?O&(0e;m^z9cT{Z`XCSI`TVB}CpOg aS13a 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 Wm&oY)GVx-$*~_(kj(ES^?D&74)337t diff --git a/NS3Mosaik/mosaik_api/include/NS3Netsim.h b/NS3Mosaik/mosaik_api/include/NS3Netsim.h index 929b27b..61d986a 100644 --- a/NS3Mosaik/mosaik_api/include/NS3Netsim.h +++ b/NS3Mosaik/mosaik_api/include/NS3Netsim.h @@ -201,11 +201,11 @@ class NS3Netsim { /** * Set up a tcp or udp server depending on what has been passed in. * - * \param address The address that will be used to assigned addresses to both the server + * \param addressPrimary The address that will be used to assign addresses to both type of servers for the primary network * \param tcpOrUdp a string that is either set to tcp or udp, indicating which kind of server will be created * \param server holds the server id */ - void setUpServer(InetSocketAddress addressIpv4, string protocol, string server); + void setUpServer(InetSocketAddress addressPrimary, string protocol, string server); /** * Sets up a tcp or udp client depending on what has been passed in diff --git a/NS3Mosaik/mosaik_api/include/ns3-helper.h b/NS3Mosaik/mosaik_api/include/ns3-helper.h index 29926bc..7f63e6e 100644 --- a/NS3Mosaik/mosaik_api/include/ns3-helper.h +++ b/NS3Mosaik/mosaik_api/include/ns3-helper.h @@ -115,15 +115,27 @@ void PrintIpAddresses(NodeContainer nodes); map CreateMapIpv4NodeId(NodeContainer nodes); /** - * Get a wifi net-device from the node passed in + * Checks the number of nodes. If the number does not match the number passed in, throws an error + * \param nodes, the node container which should be checked + * \param numberToCheck, the size nodes should equal this number + */ +void checkNumberOfNodesInContainer(NodeContainer nodes, int numberToCheck); + +/** + * Gets the address that starts with the string passed in. + * \param node, contains the node for which all the ipv4 addresses will be fetched + * \param starting, the string with which the address starts + * \return return the ipv4 address that starts with the starting string + */ +Ipv4Address getAddressForNodeStartingWith(NodeContainer node, std::string starting); + +/** + * Get a net-device of the type passed in + * \param node, the node which will be searched. */ template Ptr GetNetDeviceOfType(NodeContainer node) { - // Get the number of nodes in the node container, if larger than one, throw an error - if (node.GetN() != 1) { - throw "Number of nodes passed in is too large, the node container can only contain one node."; - } - + checkNumberOfNodesInContainer(node, 1); // Now iterate through the net devices for (int i = 0; i < node.Get(0)->GetNDevices(); i++) { // Try a dynamic cast @@ -135,8 +147,28 @@ Ptr GetNetDeviceOfType(NodeContainer node) { } // If you've gotten to this point there is no net device of this type, throw an error - throw "NetDevice of this correct type not found"; + NS_FATAL_ERROR("NetDevice of correct type not found."); } +/** + * Get a application of the type passed in + * \param node, the node which will be searched + */ +template +Ptr GetApplicationOfType(NodeContainer node) { + checkNumberOfNodesInContainer(node, 1); + // Now iterate through the net devices + for (int i = 0; i < node.Get(0)->GetNApplications(); i++) { + // Try a dynamic cast + Ptr application = DynamicCast (node.Get(0)->GetApplication(i)); + // If T is not null, successful, return the device + if (application != 0) { + return application; + } + } + + // If you've gotten to this point there is no application of this type, throw an error + NS_FATAL_ERROR("Application of correct type not found."); +} #endif /* SMARTGRID_NS3_HELPER_H_ */ diff --git a/NS3Mosaik/mosaik_api/src/NS3Netsim.cpp b/NS3Mosaik/mosaik_api/src/NS3Netsim.cpp index b42ef2e..c84eeed 100644 --- a/NS3Mosaik/mosaik_api/src/NS3Netsim.cpp +++ b/NS3Mosaik/mosaik_api/src/NS3Netsim.cpp @@ -112,7 +112,10 @@ NS3Netsim::NS3Netsim(): //--- setup simulation type GlobalValue::Bind ("SimulatorImplementationType", StringValue ("ns3::SmartgridDefaultSimulatorImpl")); - LogComponentEnable ("SmartgridNs3Main", LOG_LEVEL_ALL); +// LogComponentEnable ("SmartgridNs3Main", LOG_LEVEL_ALL); +// LogComponentEnable ("MultiClientTcpServer", LOG_LEVEL_ALL); +// LogComponentEnable ("TcpClient", LOG_LEVEL_ALL); +// LogComponentEnable ("TcpSocketBase", LOG_LEVEL_ALL); } @@ -176,7 +179,7 @@ NS3Netsim::init (string f_adjmat, //--- set address properties for ipv4 // For the primary network, the address will start with 172 - ipv4Address.SetBase ("172.0.0.0", "255.255.255.0"); + ipv4Address.SetBase ("172.0.0.0", "255.255.255.252"); //--- set application destination port sinkPort = 3030; @@ -200,7 +203,6 @@ NS3Netsim::init (string f_adjmat, NS_LOG_INFO ("Load node names and coordinates"); arrayNamesCoords = ReadCoordinatesFile (nodeCoordinatesFilename); arrayNodeCoords = loadNodeCoords(arrayNamesCoords); - PrintNamesCoordinates (nodeCoordinatesFilename.c_str (), arrayNamesCoords); if (verbose > 1) { PrintNamesCoordinates (nodeCoordinatesFilename.c_str (), arrayNamesCoords); } @@ -384,40 +386,52 @@ NS3Netsim::create (string client, string server) NS_LOG_INFO("Create server."); Ptr srvNode = Names::Find(server); - Ptr dstNode = Names::Find(server); - // Check protocol //--- verify if server already exist std::vector::iterator it = std::find(nodeServerList.begin(), nodeServerList.end(), server); //--- if not found if (it == nodeServerList.end()) { // Create the server application - setUpServer(InetSocketAddress(Ipv4Address::GetAny(), sinkPort), Inet6SocketAddress(Ipv6Address::GetAny (), sinkPort), tcpOrUdp, server); + setUpServer(InetSocketAddress(Ipv4Address::GetAny(), sinkPort), tcpOrUdp, server); NS_LOG_DEBUG("NS3Netsim::create Server: " << *iList << endl); } else { //--- end of server part NS_LOG_DEBUG("NS3Netsim::create Server already on the list: " << server << endl); } - // create client socket - NS_LOG_INFO("Create client."); - - // Get the net device depending on if the nodes are in a wifi network or a p2p network - Ipv4InterfaceAddress serverAddr; + // Declared with a dummy address so that it can be initialized + InetSocketAddress serverAddr = InetSocketAddress("192.168.1.1"); + // At this point, the server has been created, check to see if the wifi socket needs to be enabled in the server if (wifiNetworks.count(server) != 0 && wifiNetworks[server].count(client) != 0) { - std::cout << "here" << std::endl; - serverAddr = dstNode->GetObject()->GetAddress(2,0); + // The wifi needs to be enabled in the server, fetch the application + if (tcpOrUdp == "tcp") { + // Fetch the multi-client-tcp-server + Ptr serverApp = GetApplicationOfType(NodeContainer(srvNode)); + // Get the wifi address + serverAddr = InetSocketAddress(getAddressForNodeStartingWith(NodeContainer(srvNode), "192.168"), sinkPort); + + // Check if the wifi socket has been enabled + if (serverApp->GetCreateWifiSocket() == false) { + // Now enabled enable it + serverApp->SetCreateWifiSocket(true); + serverApp->m_LocalWifi = serverAddr; + } + } else if (tcpOrUdp == "udp") { + // Fetch the custom-udp-server + Ptr clientApp = GetApplicationOfType(NodeContainer(srvNode)); + } } else { - serverAddr = dstNode->GetObject()->GetAddress(2,0); + serverAddr = InetSocketAddress(getAddressForNodeStartingWith(NodeContainer(srvNode), "172.0"), sinkPort); } - InetSocketAddress remote = InetSocketAddress(serverAddr.GetLocal(), sinkPort); - std::cout << remote.GetIpv4() << std::endl; - setUpClient(AddressValue(remote), tcpOrUdp, server, client); + // create client socket + NS_LOG_INFO("Create client."); + + setUpClient(AddressValue(serverAddr), tcpOrUdp, server, client); } } void -NS3Netsim::setUpServer(std::vector addressIpv4, string protocol, string server) +NS3Netsim::setUpServer(InetSocketAddress addressPrimary, string protocol, string server) { NS_LOG_FUNCTION(this); // Where the returned application will be stored @@ -425,8 +439,7 @@ NS3Netsim::setUpServer(std::vector addressIpv4, string protoc // Switch on the protocol passed in if (protocol == "tcp") { // Set the address with which the application should be created - multiClientTcpServerHelper.SetAttribute("LocalIpv4", AddressValue(addressIpv4)); - multiClientTcpServerHelper.SetAttribute("LocalIpv6", AddressValue(addressIpv6)); + multiClientTcpServerHelper.SetAttribute("LocalPrimary", AddressValue(addressPrimary)); serverAppContainer = multiClientTcpServerHelper.Install(server); // Set the call back to extract information from a packet and sent it to the upper layer Ptr serverAppAsCorrectType = DynamicCast (serverAppContainer.Get(0)); @@ -434,8 +447,7 @@ NS3Netsim::setUpServer(std::vector addressIpv4, string protoc serverAppAsCorrectType->SetPacketReceivedCallBack(ExtractInformationFromPacketAndSendToUpperLayer); } else if (protocol == "udp") { // Set the address with which the application should be created - customUdpServerHelper.SetAttribute("LocalIpv4", AddressValue(addressIpv4)); - customUdpServerHelper.SetAttribute("LocalIpv6", AddressValue(addressIpv6)); + customUdpServerHelper.SetAttribute("LocalPrimary", AddressValue(addressPrimary)); // Create a tcp container serverAppContainer = customUdpServerHelper.Install(server); // Set the call back to extract information from a packet and sent it to the upper layer @@ -504,20 +516,16 @@ NS3Netsim::schedule (string src, string dst, string val, string val_time) } Ptr srcNode = Names::Find(src); - if (srcNode->GetNApplications() > 0) { - if (tcpOrUdp == "tcp") { - Ptr clientApp = DynamicCast (srcNode->GetApplication(0)); - if (clientApp == 0){ - clientApp = DynamicCast (srcNode->GetApplication(1)); - } - clientApp->ScheduleTransmit(val, val_time); - } else if (tcpOrUdp == "udp") { - Ptr clientApp = DynamicCast (srcNode->GetApplication(0)); - if (clientApp == 0){ - clientApp = DynamicCast (srcNode->GetApplication(1)); - } - clientApp->ScheduleTransmit(val, val_time); - } + // Try to get the correct type of application + if (tcpOrUdp == "tcp") { + Ptr clientApp = GetApplicationOfType(NodeContainer(srcNode)); + clientApp->ScheduleTransmit(val, val_time); + } else if (tcpOrUdp == "udp") { + Ptr clientApp = GetApplicationOfType(NodeContainer(srcNode)); + clientApp->ScheduleTransmit(val, val_time); + } else { + // If unknown protocol, stop and throw error + NS_FATAL_ERROR("Invalid protocol passed in"); } } @@ -546,10 +554,10 @@ NS3Netsim::runUntil (string nextStop) } } -// if (stoi(nextStop) % 100 == 0){ -// schedule ("6321", "632", to_string(-stoi(nextStop)), to_string(stoi(nextStop) + 20)); -// schedule ("6322", "632", to_string(-stoi(nextStop)), to_string(stoi(nextStop) + 20)); -// } + if (stoi(nextStop) % 100 == 0){ + schedule ("6321", "632", to_string(-stoi(nextStop)), to_string(stoi(nextStop) + 201)); + schedule ("6322", "632", to_string(-stoi(nextStop)), to_string(stoi(nextStop) + 20)); + } if (verbose > 1) { std::cout << "NS3Netsim::runUntil After_run NS3 time: " << Simulator::Now ().GetMilliSeconds () << std::endl; diff --git a/NS3Mosaik/mosaik_api/src/ns3-helper.cpp b/NS3Mosaik/mosaik_api/src/ns3-helper.cpp index d52d8e0..76db1a9 100644 --- a/NS3Mosaik/mosaik_api/src/ns3-helper.cpp +++ b/NS3Mosaik/mosaik_api/src/ns3-helper.cpp @@ -266,3 +266,27 @@ CreateMapIpv4NodeId(NodeContainer nodes) return mapIpv4NodeId; } + +void +checkNumberOfNodesInContainer(NodeContainer nodes, int numberToCheck) { + if (nodes.GetN() != numberToCheck) { + NS_FATAL_ERROR("Number of nodes passed in does not equal the desired number."); + } +} + +Ipv4Address +getAddressForNodeStartingWith(NodeContainer node, std::string starting) { + checkNumberOfNodesInContainer(node, 1); + + // Get all the ipv4 addresses + for (int i = 0; i < node.Get(0)->GetNDevices(); i++) { + // Convert the address into a string + std::ostringstream stream; + stream << node.Get(0)->GetObject()->GetAddress (i,0).GetLocal(); + std::string j = stream.str(); + if (j.rfind(starting, 0) == 0) { + return node.Get(0)->GetObject()->GetAddress (i,0).GetLocal(); + } + } + NS_FATAL_ERROR("Address not found."); +} \ No newline at end of file diff --git a/NS3Mosaik/tcp-server-and-client/include/multi-client-tcp-server.h b/NS3Mosaik/tcp-server-and-client/include/multi-client-tcp-server.h index a82c662..75afd7a 100644 --- a/NS3Mosaik/tcp-server-and-client/include/multi-client-tcp-server.h +++ b/NS3Mosaik/tcp-server-and-client/include/multi-client-tcp-server.h @@ -57,14 +57,14 @@ class MultiClientTcpServer: public Application virtual ~MultiClientTcpServer (); /** - * \return pointer to the listening socket with ipv4 address + * \return pointer to the listening socket in the primary network */ - Ptr GetListeningSocketIpv4 (void) const; + Ptr GetListeningSocketPrimary (void) const; /** - * \return pointer to the listening socket with ipv4 address + * \return pointer to the listening socket with the wifi network */ - Ptr GetListeningSocketIpv6 (void) const; + Ptr GetListeningSocketWifi (void) const; /** * \return list of pointer to accepted sockets @@ -77,8 +77,22 @@ class MultiClientTcpServer: public Application */ void SetPacketReceivedCallBack(void (*callback)(Ptr socket)); - Address m_localIpv4; //!< Local address to bind to for ipv4 socket - Address m_localIpv6; //!< Local address to bind to for the ipv6 socket + /** + * \brief Created to control the creation of the wifi-socket. This needs to be done before the application is started. + * After the application is started, calling this method will have no effect. Default is no-wifi socket creation. + * + * \param the bool value which will enable/disable the wifi creation + */ + void SetCreateWifiSocket(bool enable); + + /** + * \brief Fetch the value of the wifi socket creation bool + * \return bool indicating if the wifi socket will be created or not + */ + bool GetCreateWifiSocket(void); + + Address m_LocalPrimary; //!< The primary network ipv4 address + Address m_LocalWifi; //!< The secondary network ipv4 address, this is the wifi network address protected: virtual void DoDispose (void); @@ -134,12 +148,11 @@ class MultiClientTcpServer: public Application // When a connection is accepted in TCP, a new socket is returned // So we need to store a listening socket for this class - Ptr m_listeningSocketIpv4; //!< Listening socket for ipv4 - Ptr m_listeningSocketIpv6; //!< Listening socket for ipv6 + Ptr m_listeningPrimary; //!< Listening socket for the primary network + Ptr m_listeningWifi; //!< Listening socket for the wifi network // And a list of sockets that have been accepted std::list > m_acceptedSocketList; //!< the accepted sockets - /// Traced Callback: received packets, source address. TracedCallback, const Address &> m_rxTrace; @@ -148,6 +161,9 @@ class MultiClientTcpServer: public Application /// The function that will be called when a packet is received void (*m_packetReceivedCallback)(Ptr socket); + + /// The creation of a wifi-socket will depend on the value of this member + bool m_createWifiSocket; }; #endif //_MULTI_CLIENT_TCP_SERVER_H_ diff --git a/NS3Mosaik/tcp-server-and-client/src/multi-client-tcp-server.cc b/NS3Mosaik/tcp-server-and-client/src/multi-client-tcp-server.cc index b636d9b..bdaa71f 100644 --- a/NS3Mosaik/tcp-server-and-client/src/multi-client-tcp-server.cc +++ b/NS3Mosaik/tcp-server-and-client/src/multi-client-tcp-server.cc @@ -39,15 +39,15 @@ MultiClientTcpServer::GetTypeId (void) .SetParent () .SetGroupName("Applications") .AddConstructor () - .AddAttribute("LocalIpv4", + .AddAttribute("LocalPrimary", "The value on which to Bind the rx socket.", AddressValue (), - MakeAddressAccessor (&MultiClientTcpServer::m_localIpv4), + MakeAddressAccessor (&MultiClientTcpServer::m_LocalPrimary), MakeAddressChecker()) - .AddAttribute("LocalIpv6", + .AddAttribute("LocalWifi", "The value on which to Bind the rx socket.", AddressValue (), - MakeAddressAccessor (&MultiClientTcpServer::m_localIpv6), + MakeAddressAccessor (&MultiClientTcpServer::m_LocalWifi), MakeAddressChecker()) .AddTraceSource("Rx", "A packet has been received", @@ -65,9 +65,10 @@ MultiClientTcpServer::MultiClientTcpServer() { NS_LOG_FUNCTION(this); // Set the socket to null - m_listeningSocketIpv4 = 0; - m_listeningSocketIpv6 = 0; + m_listeningPrimary = 0; + m_listeningWifi = 0; m_packetReceivedCallback = 0; + m_createWifiSocket = false; } MultiClientTcpServer::~MultiClientTcpServer() @@ -76,17 +77,17 @@ MultiClientTcpServer::~MultiClientTcpServer() } Ptr -MultiClientTcpServer::GetListeningSocketIpv4 (void) const +MultiClientTcpServer::GetListeningSocketPrimary (void) const { NS_LOG_FUNCTION (this); - return m_listeningSocketIpv4; + return m_listeningPrimary; } Ptr -MultiClientTcpServer::GetListeningSocketIpv6 (void) const +MultiClientTcpServer::GetListeningSocketWifi (void) const { NS_LOG_FUNCTION (this); - return m_listeningSocketIpv6; + return m_listeningWifi; } std::list > @@ -101,8 +102,8 @@ MultiClientTcpServer::DoDispose (void) { NS_LOG_FUNCTION (this); // Clear the listening socket - m_listeningSocketIpv4 = 0; - m_listeningSocketIpv6 = 0; + m_listeningPrimary = 0; + m_listeningWifi = 0; // Clear the accepted socket m_acceptedSocketList.clear (); @@ -121,14 +122,14 @@ void MultiClientTcpServer::StartApplication() { NS_LOG_FUNCTION(this); - // Create ipv4 listening socket if it does not exist - if (m_listeningSocketIpv4 == 0) { - m_listeningSocketIpv4 = CreateListeningSocket(m_localIpv4); + // Create ipv4 primary listening socket if it does not exist + if (m_listeningPrimary == 0) { + m_listeningPrimary = CreateListeningSocket(m_LocalPrimary); } - // Create ipv6 listening socket if it does not exist - if (m_listeningSocketIpv6 == 0) { - m_listeningSocketIpv6 = CreateListeningSocket(m_localIpv6); + // Create ipv4 wifi listening socket if it does not exist + if (m_listeningWifi == 0 && m_createWifiSocket) { + m_listeningWifi = CreateListeningSocket(m_LocalWifi); } } @@ -180,13 +181,13 @@ MultiClientTcpServer::StopApplication() } // Close the listening sockets - if (m_listeningSocketIpv4 != 0) + if (m_listeningPrimary != 0) { - CloseListeningSocket(m_listeningSocketIpv4); + CloseListeningSocket(m_listeningPrimary); } - if (m_listeningSocketIpv6 != 0) + if (m_listeningWifi != 0) { - CloseListeningSocket(m_listeningSocketIpv6); + CloseListeningSocket(m_listeningWifi); } } @@ -235,7 +236,8 @@ MultiClientTcpServer::HandleAccept (Ptr socket, const Address& from) } void -MultiClientTcpServer::HandleRead(Ptr socket) { +MultiClientTcpServer::HandleRead(Ptr socket) +{ NS_LOG_FUNCTION (this); // Call the callback in the simulator to let it know that a message has been received if (m_packetReceivedCallback != NULL) @@ -243,3 +245,17 @@ MultiClientTcpServer::HandleRead(Ptr socket) { m_packetReceivedCallback(socket); } } + +void +MultiClientTcpServer::SetCreateWifiSocket(bool enable) +{ + NS_LOG_FUNCTION(this); + m_createWifiSocket = enable; +} + +bool +MultiClientTcpServer::GetCreateWifiSocket(void) +{ + NS_LOG_FUNCTION(this); + return m_createWifiSocket; +} \ No newline at end of file From b211f4b6005da811575bb2f69f9f8ed7cd9a8c1e Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Thu, 16 Jul 2020 17:32:47 -0600 Subject: [PATCH 05/22] Both TCP and UDP applications ready to go. - TCP applications and UDP applications ready to go with wifi net devices - Tested with multiple networks very close to each other which could cause interference - Routing within wifi still needs to be done so packets can be routed to the server if server and client are not in direct contact. --- NS3Mosaik/NS3MosaikSim | Bin 1937904 -> 1942824 bytes NS3Mosaik/mosaik_api/src/NS3Netsim.cpp | 26 ++++++--- .../tcp-server-and-client/src/tcp-client.cc | 2 - .../include/custom-udp-server.h | 41 ++++++++++++-- .../src/custom-udp-server.cc | 52 ++++++++++++++---- 5 files changed, 94 insertions(+), 27 deletions(-) diff --git a/NS3Mosaik/NS3MosaikSim b/NS3Mosaik/NS3MosaikSim index d71fc8f6f98400463cdd8c5412bf9ed7ffe4cab1..b451381148a5d8679eb242d35f6e416e7da0ada4 100755 GIT binary patch delta 120938 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%0D8HsM;LnY+M_ce=yyA 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�Dvrds|abzK4 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

|Im}=957e@9ln#9$i#`9pW&8$p zNi^4?O2%ox+OZs^hpQG2<=B4oj0DeCZVA53hQy(sh!QAH*5W@n5=P$ZFT&HBGY3k< z;jsl@Y(Ilc?g{b#RY~x)Ta-eNlG`oDjm%3wr((^y0&6AWa0QAUPMu#L~+n}?>#>1tt z#FnSCbpadsl@vg9o}V0QN+qTgdVoYPmnL}kH0J+v7TRx(;$ljLeN>DIF)MnpN#Ct6f!>LDZa?qqgZ7sqb4g3FCdlT>)kLVBBJA_!` z#uBnvE)tU1VhM=|3Be7C#vY}_Qer7lqFT$1Cc*7>tz}SasoF&~qSjcGmbO$CRZF#a zUqRARluEwenR)L*`~QFc?|HsFPwqQ&&Y3ea=bYI$TyPsmUU6g~rUe9NxkGWRL@4{} z!Sq}?$_Su%kq-)LvVNda1k{j#PQv9X3nvN!zO$c&;ZcYKGWk(&HT1ZY*$wB$DQkDj( zHU!FYn!=uK>I^%|8TPLboOnQ4B9g5{0xO~?Awma;Bq-!^^BS;n9~#l zNAjnrPbr09K^$sG4m5eRNN}Lm#!_faF*Z)ArAAU@sMd+{@ez?1q8tUvnxrkNSIE|= z&Y()VXGjU}*&8c9&mnewL4$fDVnKrlKB3y3#@wO>`&WTHivb>$(-4xW+&7{%p?t~P zMP2quexXy!Cf~7rayx<3Bcu1e35DBVSelFEQZK%FFj$dMl||}cwnMv7y?qylBHccY zlciK_wzj!l?7@>P*o0IVM504_s7KY3Qetzf2xBK$DZt3OMNevu=n}Z)fFtG`_Y212 zc$>6my1jF?{n4WeRF>?;;#*x1qO_uIq|M11Y@M>4vefNt74!GHFM(tNGfbkd=yhc4 z7*8QBEV?4>1|3#J8Ua7rqG{7%LQB;C0`|TROCvgGjaZ+G1WYtc4V+Fc4B+zta+%2r zAPLVtc^S}GX0nJ8wU36(CPFo|!LJNPFJg|%u@Dpb4?!UHr|LXtLoUSB+4cI6>Z_Ne zF|iO6U!?7T&rnxHfV~lh%zGk{xK}j*{AJHdz>f$x+Ca_inI5r#XX)?|Ermx}(L>$U zm?v5l|Ca8e2+N)hnKKDUt1pIC5cQX`B_j1hz&IQ^uyF|wS;-nS--{APO}J>OAS1$S z@dzgqL)Jm^r(>cI)v}HG7DU!0>9s&ap*<23681z|lp*#7^Mv_|e|OK zdMMEY(L-sEERadJK_?TiNP?-2gu5QOE1|4wKK#ghrFO;l5#EG_Om%%zerLYY$o%L)7Z=DD-O}3~j2&Xa*!MjarsU94%DrC&}($E1Y)qIrmtg z)G^O476N>CKZc^8`3v_ba$f;2brVDsXSs(OF%mGyXT&}+RTBq7wJneU<$eL`PpF95 zBEKZ}Lh0T@?sQS~Pz*JCFO*7Kpw=2DPOcE`gO?>nINSSc-vKK}l_xZJj0)}UPuuf4 z3zZt?1Q*z77k3>O_m1|?aI;K4`XYjKQT6v+u9q*B2_ASa2ZESfq?s4)H%0DM|i= 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%0Dk=s&seAEKW_KwD-M##gZR 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 - wifiNetworks["632"].insert("6321"); - wifiNetworks["632"].insert("6322"); // Create a WiFi network according to the nodes passed in, each set inside the vector is a network that needs to be created for (auto network = wifiNetworks.begin(); network != wifiNetworks.end(); network++) { // Grab the end node of the primary network @@ -314,6 +310,7 @@ NS3Netsim::init (string f_adjmat, // Connect all the devices NetDeviceContainer devices = wifi.Install (wifiPhy, wifiMac, networkNodes); + wifiPhy.EnablePcapAll("pcapNS3Netsim.pcap"); // Assign the addresses ipv4Address.Assign(devices); ipv4Address.NewNetwork(); @@ -417,7 +414,16 @@ NS3Netsim::create (string client, string server) } } else if (tcpOrUdp == "udp") { // Fetch the custom-udp-server - Ptr clientApp = GetApplicationOfType(NodeContainer(srvNode)); + Ptr serverApp = GetApplicationOfType(NodeContainer(srvNode)); + // Get the wifi address + serverAddr = InetSocketAddress(getAddressForNodeStartingWith(NodeContainer(srvNode), "192.168"), sinkPort); + + // Check if the wifi socket has been enabled + if (serverApp->GetCreateWifiSocket() == false) { + // Now enabled enable it + serverApp->SetCreateWifiSocket(true); + serverApp->m_LocalWifi = serverAddr; + } } } else { serverAddr = InetSocketAddress(getAddressForNodeStartingWith(NodeContainer(srvNode), "172.0"), sinkPort); @@ -555,8 +561,10 @@ NS3Netsim::runUntil (string nextStop) } if (stoi(nextStop) % 100 == 0){ - schedule ("6321", "632", to_string(-stoi(nextStop)), to_string(stoi(nextStop) + 201)); - schedule ("6322", "632", to_string(-stoi(nextStop)), to_string(stoi(nextStop) + 20)); + schedule ("6321", "632", to_string(20), to_string(stoi(nextStop) + 20)); + schedule ("6322", "632", to_string(20), to_string(stoi(nextStop) + 20)); + schedule ("6501", "650", to_string(30), to_string(stoi(nextStop) + 20)); + schedule ("6502", "650", to_string(30), to_string(stoi(nextStop) + 20)); } if (verbose > 1) { diff --git a/NS3Mosaik/tcp-server-and-client/src/tcp-client.cc b/NS3Mosaik/tcp-server-and-client/src/tcp-client.cc index c2a2506..79fe208 100644 --- a/NS3Mosaik/tcp-server-and-client/src/tcp-client.cc +++ b/NS3Mosaik/tcp-server-and-client/src/tcp-client.cc @@ -178,8 +178,6 @@ TcpClient::SendMessage (string message) << " by nodeName: " << Names::FindName(m_socket->GetNode ()) << " MsgSize: " << message.size() << std::endl; filePacketsSent.close(); - } else { - std::cout << "m_socket is 0" << std::endl; } } diff --git a/NS3Mosaik/udp-server-client/include/custom-udp-server.h b/NS3Mosaik/udp-server-client/include/custom-udp-server.h index bf81dae..ee3004a 100644 --- a/NS3Mosaik/udp-server-client/include/custom-udp-server.h +++ b/NS3Mosaik/udp-server-client/include/custom-udp-server.h @@ -43,11 +43,42 @@ class CustomUdpServer: public Application { * \brief Configures the server */ static TypeId GetTypeId (void); + + CustomUdpServer (); + virtual ~CustomUdpServer (); + /** * \brief set the callback function that is called when a packet is received * \param callback the function to which the callback is set. */ void SetPacketReceivedCallBack(void (*callback)(Ptr socket)); + + /** + * \return pointer to the listening socket in the primary network + */ + Ptr GetListeningSocketPrimary (void) const; + + /** + * \return pointer to the listening socket with the wifi network + */ + Ptr GetListeningSocketWifi (void) const; + + /** + * \brief Created to control the creation of the wifi-socket. This needs to be done before the application is started. + * After the application is started, calling this method will have no effect. Default is no-wifi socket creation. + * + * \param the bool value which will enable/disable the wifi creation + */ + void SetCreateWifiSocket(bool enable); + + /** + * \brief Fetch the value of the wifi socket creation bool + * \return bool indicating if the wifi socket will be created or not + */ + bool GetCreateWifiSocket(void); + + Address m_LocalPrimary; //!< The primary network ipv4 address + Address m_LocalWifi; //!< The secondary network ipv4 address, this is the wifi network address private: virtual void StartApplication (void); virtual void StopApplication (void); @@ -71,13 +102,15 @@ class CustomUdpServer: public Application { virtual void HandleRead (Ptr socket); /// The function that will be called when a packet is received void (*m_packetReceivedCallback)(Ptr socket); - Ptr m_socketIpv4; //!< Socket that will be used to send the messages for ipv4 - Ptr m_socketIpv6; //!< Socket that will be used to send the messages for ipv6 - Address m_localIpv4; //!< Local address to bind to for ipv4 socket - Address m_localIpv6; //!< Local address to bind to for ipv4 socket + + Ptr m_socketPrimary; //!< Socket for the primary network + Ptr m_socketWifi; //!< Socket for the wifi network TracedCallback > m_rxTrace; TracedCallback, const Address &, const Address &> m_rxTraceWithAddresses; + + /// The creation of a wifi-socket will depend on the value of this member + bool m_createWifiSocket; }; #endif //_CUSTOM_UDP_SERVER_H_ diff --git a/NS3Mosaik/udp-server-client/src/custom-udp-server.cc b/NS3Mosaik/udp-server-client/src/custom-udp-server.cc index 872dd34..f782902 100644 --- a/NS3Mosaik/udp-server-client/src/custom-udp-server.cc +++ b/NS3Mosaik/udp-server-client/src/custom-udp-server.cc @@ -49,15 +49,15 @@ CustomUdpServer::GetTypeId (void) .SetParent () .SetGroupName("Applications") .AddConstructor () - .AddAttribute("LocalIpv4", + .AddAttribute("LocalPrimary", "The value on which to Bind the rx socket.", AddressValue (), - MakeAddressAccessor (&CustomUdpServer::m_localIpv4), + MakeAddressAccessor (&CustomUdpServer::m_LocalPrimary), MakeAddressChecker()) - .AddAttribute("LocalIpv6", + .AddAttribute("LocalWifi", "The value on which to Bind the rx socket.", AddressValue (), - MakeAddressAccessor (&CustomUdpServer::m_localIpv6), + MakeAddressAccessor (&CustomUdpServer::m_LocalWifi), MakeAddressChecker()) .AddTraceSource ("Rx", "A packet has been received", MakeTraceSourceAccessor (&CustomUdpServer::m_rxTrace), @@ -69,6 +69,20 @@ CustomUdpServer::GetTypeId (void) return tid; } +CustomUdpServer::CustomUdpServer() +{ + NS_LOG_FUNCTION(this); + // Set the socket to null + m_socketPrimary = 0; + m_socketWifi = 0; + m_createWifiSocket = false; +} + +CustomUdpServer::~CustomUdpServer() +{ + NS_LOG_FUNCTION (this); +} + void CustomUdpServer::HandleRead(Ptr socket) { NS_LOG_FUNCTION (this); @@ -90,14 +104,14 @@ CustomUdpServer::StartApplication (void) { NS_LOG_FUNCTION(this); // Create the socket if it does not already exist - if (m_socketIpv4 == 0) + if (m_socketPrimary == 0) { - m_socketIpv4 = CreateSocket(m_localIpv4); + m_socketPrimary = CreateSocket(m_LocalPrimary); } - if (m_socketIpv6 == 0) + if (m_socketWifi == 0 && m_createWifiSocket == true) { - m_socketIpv6 = CreateSocket(m_localIpv6); + m_socketWifi = CreateSocket(m_LocalWifi); } } @@ -132,14 +146,14 @@ void CustomUdpServer::StopApplication (void) { // Close the socket - if (m_socketIpv4 != 0) + if (m_socketPrimary != 0) { - CloseSocket(m_socketIpv4); + CloseSocket(m_socketPrimary); } - if (m_socketIpv6 != 0) + if (m_socketWifi != 0) { - CloseSocket(m_socketIpv6); + CloseSocket(m_socketWifi); } } @@ -149,4 +163,18 @@ CustomUdpServer::CloseSocket(Ptr socket) NS_LOG_FUNCTION(this); socket->Close (); socket->SetRecvCallback (MakeNullCallback > ()); +} + +void +CustomUdpServer::SetCreateWifiSocket(bool enable) +{ + NS_LOG_FUNCTION(this); + m_createWifiSocket = enable; +} + +bool +CustomUdpServer::GetCreateWifiSocket(void) +{ + NS_LOG_FUNCTION(this); + return m_createWifiSocket; } \ No newline at end of file From e7bb257d85bf971308672529f8206835b5713f94 Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Wed, 29 Jul 2020 12:01:50 -0600 Subject: [PATCH 06/22] Starting commit --- NS3Mosaik/mosaik_api/include/NS3Netsim.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/NS3Mosaik/mosaik_api/include/NS3Netsim.h b/NS3Mosaik/mosaik_api/include/NS3Netsim.h index 61d986a..2e65d58 100644 --- a/NS3Mosaik/mosaik_api/include/NS3Netsim.h +++ b/NS3Mosaik/mosaik_api/include/NS3Netsim.h @@ -229,9 +229,6 @@ class NS3Netsim { string LinkDelay; ///< Uniform link delay string LinkErrorRate; ///< Uniform Link error rate uint32_t linkCount; ///< Network link count - vector p2pDevices; ///< Vector with all link devices - vector lrWpanDevices; ///< Vector with all lrwpan devices - vector sixlowpanDevices; ///< Vector with all sixlowpan devices Ptr nodePositionAlloc; ///< Pointer to node position allocation From d3f86cc63a5e51359a6d013422961f329d7e53d5 Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Wed, 29 Jul 2020 15:26:09 -0600 Subject: [PATCH 07/22] New network file added. --- IEEE13Node_BusXY.csv | 16 ++ NS3Mosaik/mosaik_api/src/MosaikSim.cpp | 1 + .../data/IEEE13Node-adjacency_matrix.txt | 34 ++- .../data/IEEE13Node_AppConnections_Tap.csv | 2 - .../tapcontrol/data/IEEE13Node_BusXY.csv | 2 - .../data/IEEE13Nodeckt_Actives_Tap.csv | 2 - TapControl/tapcontrol/data/ieee13.json | 206 ++++++++++++++++++ ad_mat.csv | 16 ++ 8 files changed, 255 insertions(+), 24 deletions(-) create mode 100644 IEEE13Node_BusXY.csv create mode 100644 TapControl/tapcontrol/data/ieee13.json create mode 100644 ad_mat.csv diff --git a/IEEE13Node_BusXY.csv b/IEEE13Node_BusXY.csv new file mode 100644 index 0000000..ba14e1e --- /dev/null +++ b/IEEE13Node_BusXY.csv @@ -0,0 +1,16 @@ +SourceBus, 200, 400 +650, 200, 350 +RG60, 200, 300 +646, 0, 250 +645, 100, 250 +632, 200, 250 +633, 350, 250 +634, 400, 250 +670, 200, 200 +611, 0, 100 +684, 100, 100 +671, 200, 100 +692, 250, 100 +675, 400, 100 +652, 100, 0 +680, 200, 0 diff --git a/NS3Mosaik/mosaik_api/src/MosaikSim.cpp b/NS3Mosaik/mosaik_api/src/MosaikSim.cpp index 84beb55..78b87d6 100644 --- a/NS3Mosaik/mosaik_api/src/MosaikSim.cpp +++ b/NS3Mosaik/mosaik_api/src/MosaikSim.cpp @@ -601,6 +601,7 @@ MosaikSim::create(Json::Value args, Json::Value kwargs) } return result; + exit(0); } diff --git a/TapControl/tapcontrol/data/IEEE13Node-adjacency_matrix.txt b/TapControl/tapcontrol/data/IEEE13Node-adjacency_matrix.txt index 198f26d..86394ae 100644 --- a/TapControl/tapcontrol/data/IEEE13Node-adjacency_matrix.txt +++ b/TapControl/tapcontrol/data/IEEE13Node-adjacency_matrix.txt @@ -1,18 +1,16 @@ -0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 0 -0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 0 0 -0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 +0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 diff --git a/TapControl/tapcontrol/data/IEEE13Node_AppConnections_Tap.csv b/TapControl/tapcontrol/data/IEEE13Node_AppConnections_Tap.csv index febdb69..b0f925a 100644 --- a/TapControl/tapcontrol/data/IEEE13Node_AppConnections_Tap.csv +++ b/TapControl/tapcontrol/data/IEEE13Node_AppConnections_Tap.csv @@ -1,4 +1,2 @@ 611,632,sensing 632,650,acting -6321,632,sensing -6322,632,sensing \ No newline at end of file diff --git a/TapControl/tapcontrol/data/IEEE13Node_BusXY.csv b/TapControl/tapcontrol/data/IEEE13Node_BusXY.csv index e31d240..ba14e1e 100644 --- a/TapControl/tapcontrol/data/IEEE13Node_BusXY.csv +++ b/TapControl/tapcontrol/data/IEEE13Node_BusXY.csv @@ -14,5 +14,3 @@ RG60, 200, 300 675, 400, 100 652, 100, 0 680, 200, 0 -6321, 201, 251 -6322, 201, 251 \ No newline at end of file diff --git a/TapControl/tapcontrol/data/IEEE13Nodeckt_Actives_Tap.csv b/TapControl/tapcontrol/data/IEEE13Nodeckt_Actives_Tap.csv index c5c66f6..3cd68a8 100644 --- a/TapControl/tapcontrol/data/IEEE13Nodeckt_Actives_Tap.csv +++ b/TapControl/tapcontrol/data/IEEE13Nodeckt_Actives_Tap.csv @@ -1,6 +1,4 @@ Sensor_611,getV,Line.684611,BUS2,PHASE_3 -Sensor_6321,getV,Line.684611,BUS2,PHASE_3 -Sensor_6322,getV,Line.684611,BUS2,PHASE_3 Actuator_650,setTap,Transformer.REG3,BUS1,PHASE_3 Prober_611-V3,getV,Line.684611,BUS2,PHASE_3 Prober_650-T3,getTap,Transformer.REG3,BUS1,PHASE_3 diff --git a/TapControl/tapcontrol/data/ieee13.json b/TapControl/tapcontrol/data/ieee13.json new file mode 100644 index 0000000..ca4ec97 --- /dev/null +++ b/TapControl/tapcontrol/data/ieee13.json @@ -0,0 +1,206 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "0", + "power_network_id": "SourceBus", + "location": { + "x": "200", + "y": "400" + } + }, + { + "id": "1", + "power_network_id": "650", + "location": { + "x": "200", + "y": "350" + } + }, + { + "id": "2", + "power_network_id": "RG60", + "location": { + "x": "200", + "y": "300" + } + }, + { + "id": "3", + "power_network_id": "646", + "location": { + "x": "0", + "y": "250" + } + }, + { + "id": "4", + "power_network_id": "645", + "location": { + "x": "100", + "y": "250" + } + }, + { + "id": "5", + "power_network_id": "632", + "location": { + "x": "200", + "y": "250" + } + }, + { + "id": "6", + "power_network_id": "633", + "location": { + "x": "350", + "y": "250" + } + }, + { + "id": "7", + "power_network_id": "634", + "location": { + "x": "400", + "y": "250" + } + }, + { + "id": "8", + "power_network_id": "670", + "location": { + "x": "200", + "y": "200" + } + }, + { + "id": "9", + "power_network_id": "611", + "location": { + "x": "0", + "y": "100" + } + }, + { + "id": "10", + "power_network_id": "684", + "location": { + "x": "100", + "y": "100" + } + }, + { + "id": "11", + "power_network_id": "671", + "location": { + "x": "200", + "y": "100" + } + }, + { + "id": "12", + "power_network_id": "692", + "location": { + "x": "250", + "y": "100" + } + }, + { + "id": "13", + "power_network_id": "675", + "location": { + "x": "400", + "y": "100" + } + }, + { + "id": "14", + "power_network_id": "652", + "location": { + "x": "100", + "y": "0" + } + }, + { + "id": "15", + "power_network_id": "680", + "location": { + "x": "200", + "y": "0" + } + } + ], + "network_layout": [ + { + "nodes":["632", "645"], + "type": "p2p" + }, + { + "nodes":["670", "671"], + "type": "p2p" + }, + { + "nodes":["632", "RG60"], + "type": "p2p" + }, + { + "nodes":["650", "SourceBus"], + "type": "p2p" + }, + { + "nodes":["633", "634"], + "type": "p2p" + }, + { + "nodes":["671", "692"], + "type": "p2p" + }, + { + "nodes":["675", "692"], + "type": "p2p" + }, + { + "nodes":["671", "684"], + "type": "p2p" + }, + { + "nodes":["652", "684"], + "type": "p2p" + }, + { + "nodes":["632", "670"], + "type": "p2p" + }, + { + "nodes":["671", "680"], + "type": "p2p" + }, + { + "nodes":["611", "684"], + "type": "p2p" + }, + { + "nodes":["645", "646"], + "type": "p2p" + }, + { + "nodes":["632", "633"], + "type": "p2p" + }, + { + "nodes":["650", "RG60"], + "type": "p2p" + } + ] + }, + "app_connections": [ + { + "server": "632", + "client": "611" + }, + { + "server": "632", + "client": "650" + } + ] +} \ No newline at end of file diff --git a/ad_mat.csv b/ad_mat.csv new file mode 100644 index 0000000..1948966 --- /dev/null +++ b/ad_mat.csv @@ -0,0 +1,16 @@ +0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 +0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 +0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 +0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 +0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0 +0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1 +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0 +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 From dff82ee11e071feba37995fcd5719dc67887291e Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Wed, 29 Jul 2020 17:28:27 -0600 Subject: [PATCH 08/22] Updated config file to include secondary network --- NS3Mosaik/mosaik_api/include/NS3Netsim.h | 1 + NS3Mosaik/mosaik_api/src/MosaikSim.cpp | 2 + TapControl/tapcontrol/data/ieee13.json | 94 +++++++++++++++++++----- TapControl/tapcontrol/simulator_demo.py | 37 +--------- 4 files changed, 82 insertions(+), 52 deletions(-) diff --git a/NS3Mosaik/mosaik_api/include/NS3Netsim.h b/NS3Mosaik/mosaik_api/include/NS3Netsim.h index 2e65d58..f284aad 100644 --- a/NS3Mosaik/mosaik_api/include/NS3Netsim.h +++ b/NS3Mosaik/mosaik_api/include/NS3Netsim.h @@ -229,6 +229,7 @@ class NS3Netsim { string LinkDelay; ///< Uniform link delay string LinkErrorRate; ///< Uniform Link error rate uint32_t linkCount; ///< Network link count + vector p2pDevices; ///< Vector with all link devices Ptr nodePositionAlloc; ///< Pointer to node position allocation diff --git a/NS3Mosaik/mosaik_api/src/MosaikSim.cpp b/NS3Mosaik/mosaik_api/src/MosaikSim.cpp index 78b87d6..407ddac 100644 --- a/NS3Mosaik/mosaik_api/src/MosaikSim.cpp +++ b/NS3Mosaik/mosaik_api/src/MosaikSim.cpp @@ -553,12 +553,14 @@ MosaikSim::create(Json::Value args, Json::Value kwargs) std::string result; std::string entity; + std::cout << "CREATING" << std::endl; mosaikNum = args[0].asInt(); mosaikSimModel = args[1].asString(); if (verbose > 1) std::cout << "MosaikSim::create mosaikNum: " << mosaikNum << " - mosaikSimModel: " << mosaikSimModel << std::endl; + std::cout << kwargs << std::endl; //--- Store simulator parameters for (auto const& key : kwargs.getMemberNames()) { netsimParams[key] = (kwargs[key]).asString(); diff --git a/TapControl/tapcontrol/data/ieee13.json b/TapControl/tapcontrol/data/ieee13.json index ca4ec97..753639e 100644 --- a/TapControl/tapcontrol/data/ieee13.json +++ b/TapControl/tapcontrol/data/ieee13.json @@ -132,75 +132,131 @@ ], "network_layout": [ { - "nodes":["632", "645"], + "nodes":["0", "1"], "type": "p2p" }, { - "nodes":["670", "671"], + "nodes":["1", "2"], "type": "p2p" }, { - "nodes":["632", "RG60"], + "nodes":["6", "7"], "type": "p2p" }, { - "nodes":["650", "SourceBus"], + "nodes":["10", "11"], "type": "p2p" }, { - "nodes":["633", "634"], + "nodes":["4", "5"], "type": "p2p" }, { - "nodes":["671", "692"], + "nodes":["5", "6"], "type": "p2p" }, { - "nodes":["675", "692"], + "nodes":["8", "11"], "type": "p2p" }, { - "nodes":["671", "684"], + "nodes":["11", "12"], "type": "p2p" }, { - "nodes":["652", "684"], + "nodes":["12", "13"], "type": "p2p" }, { - "nodes":["632", "670"], + "nodes":["9", "10"], "type": "p2p" }, { - "nodes":["671", "680"], + "nodes":["10", "14"], "type": "p2p" }, { - "nodes":["611", "684"], + "nodes":["11", "15"], "type": "p2p" }, { - "nodes":["645", "646"], + "nodes":["2", "5"], "type": "p2p" }, { - "nodes":["632", "633"], + "nodes":["3", "4"], "type": "p2p" }, { - "nodes":["650", "RG60"], + "nodes":["5", "8"], "type": "p2p" } ] }, + "secondary_network": { + "nodes": [ + { + "id": "16", + "access_point": false, + "power_network_id": "6321", + "location": { + "x": "150", + "y": "250" + } + }, + { + "id": "17", + "access_point": false, + "power_network_id": "6322", + "location": { + "x": "100", + "y": "350" + } + }, + { + "id": "18", + "access_point": true, + "location": { + "x": "100", + "y": "300" + } + } + ], + "network_layout": [ + { + "nodes": ["16", "5"], + "type": "wifi" + }, + { + "nodes": ["18", "5"], + "type": "wifi" + }, + { + "nodes": ["18", "17"], + "type": "wifi" + } + ] + }, "app_connections": [ { - "server": "632", - "client": "611" + "server": "5", + "client": "9", + "client_type": "sensor" }, { - "server": "632", - "client": "650" + "server": "1", + "client": "5", + "client_type": "controller" + }, + { + "server": "5", + "client": "9", + "client_type": "sensor" + }, + { + "server": "5", + "client": "9", + "client_type": "sensor" } ] } \ No newline at end of file diff --git a/TapControl/tapcontrol/simulator_demo.py b/TapControl/tapcontrol/simulator_demo.py index fa1f6d6..68e6787 100644 --- a/TapControl/tapcontrol/simulator_demo.py +++ b/TapControl/tapcontrol/simulator_demo.py @@ -192,12 +192,14 @@ def create_scenario( world, args ): #--- Transporter instances (Pktnet) transporters = [] for client, server, role in appconLinks: + print("TRANSPORTER") created_transporter = False for transporter in transporters: transporter_instance = 'Transp_' + str(client) + '-' + str(server) if (transporter_instance == transporter.eid): created_transporter = True if not created_transporter: + print(client, server) transporters.append(pktnetsim.Transporter(src=client, dst=server)) #--- Actuator instances @@ -249,19 +251,7 @@ def create_scenario( world, args ): for transporter in transporters: if (transporter_instance == transporter.eid): world.connect(transporter, controller, 'v', 't') - print('Connect', transporter.eid, 'to', controller.eid) - - #--- Sensor to Controller -# for client, server, role in appconLinks: -# if (role == 'sensing'): -# for sensor in sensors: -# sensor_instance = 'Sensor_' + str(client) -# if (sensor_instance == sensor.eid): -# for controller in controllers: -# controller_instance = 'Control_' + str(server) -# if (controller_instance == controller.eid): -# world.connect(sensor, controller, 'v', 't') -# print('Connect', sensor.eid, 'to', controller.eid) + print('Connect', transporter.eid, 'to', controller.eid) #--- Controller to PktNet for client, server, role in appconLinks: @@ -287,21 +277,7 @@ def create_scenario( world, args ): if (transporter_instance == transporter.eid): world.connect(transporter, actuator, 'v', 't', time_shifted=True, initial_data={'v': None, 't': None}) - print('Connect', transporter.eid, 'to', actuator.eid) - - #--- Controller to Actuator -# for client, server, role in appconLinks: -# if (role == 'acting'): -# for controller in controllers: -# controller_instance = 'Control_' + str(client) -# if (controller_instance == controller.eid): -# for actuator in actuators: -# actuator_instance = 'Actuator_' + str(server) -# if (actuator_instance == actuator.eid): -# print('Connect', controller.eid, 'to', actuator.eid) -# world.connect(controller, actuator, 'v', 't', -# time_shifted=True, initial_data={'v': None, 't': None}) - + print('Connect', transporter.eid, 'to', actuator.eid) #--- #--- Simulators to Monitor @@ -312,11 +288,6 @@ def create_scenario( world, args ): for sensor in sensors: print('Connect', sensor.eid, 'to', monitor.sid) - #--- PktNet(Transporter) to Monitor -# mosaik.util.connect_many_to_one(world, transporters, monitor, 'v', 't') -# for transporter in transporters: -# print('Connect', transporter.eid, 'to', monitor.sid) - #--- Controller to Monitor mosaik.util.connect_many_to_one(world, controllers, monitor, 'v', 't') for controller in controllers: From 84c8d240e277d686d99e1c0f84091b0246ecc63e Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Thu, 30 Jul 2020 18:33:15 -0600 Subject: [PATCH 09/22] Creating of Config Reader and Node class with Tests - Started creation of Config reader, this will read the file passed into the simulator once - Class to store the information on a node has also been created - Tests for the node have also been created --- ConfigReader/ConfigReader.py | 17 +++ ConfigReader/Node.py | 81 +++++++++++++ ConfigReader/NodeTester.py | 216 +++++++++++++++++++++++++++++++++++ 3 files changed, 314 insertions(+) create mode 100644 ConfigReader/ConfigReader.py create mode 100644 ConfigReader/Node.py create mode 100644 ConfigReader/NodeTester.py diff --git a/ConfigReader/ConfigReader.py b/ConfigReader/ConfigReader.py new file mode 100644 index 0000000..ca51f45 --- /dev/null +++ b/ConfigReader/ConfigReader.py @@ -0,0 +1,17 @@ +import json + + +class ConfigReader: + """ + Class was created to read the config file passed in. This is done so that the file is only read once and then the + data can be passed to each simulator without having to read the file again. + """ + file = "" + + def __init__(self, file): + """ + The initializer, saves the file pointer passed in. Since the setting of file starts reading the file, this will + also read the file passed in + :param file: + """ + self.file = file diff --git a/ConfigReader/Node.py b/ConfigReader/Node.py new file mode 100644 index 0000000..b48f14e --- /dev/null +++ b/ConfigReader/Node.py @@ -0,0 +1,81 @@ +class Node: + """ + Class was created to store the information on a node. Solely meant to be used by ConfigReader + """ + # Stores the id of the node in the power system + power_id = "" + # Stores the id of the node in the network + network_id = "" + # Stores the network of the system + location = {} + + def __init__(self, power_id, network_id, location): + """ + Validates that all the data necessary is present and is of the correct type and then saves it + :param power_id: + :param network_id: + :param location: + """ + self.__check_power_id_type(power_id) + self.__check_network_id_type(network_id) + self.__check_location_coordinates(location) + + self.power_id = power_id + self.network_id = network_id + self.location = location + + def __setattr__(self, key, value): + """ + Overridden to check that the value being set to the members is correct before writing it + :param key: + :param value: + :return: + """ + if key == "power_id": + self.__check_power_id_type(value) + elif key == "network_id": + self.__check_network_id_type(value) + elif key == "location": + self.__check_location_coordinates(value) + + super(Node, self).__setattr__(key, value) + + def __check_power_id_type(self, power_id): + """ + Checks that the power id passed in is a non-empty string. + :param power_id: + :return: + """ + self.__check_non_empty_non_none_string(power_id) + + def __check_network_id_type(self, network_id): + """ + Checks that the network id passed in is a non-empty string. + :param network_id: + :return: + """ + self.__check_non_empty_non_none_string(network_id) + + def __check_non_empty_non_none_string(self, to_check): + """ + Created to check that to_check is not None, is not an empty string and is not of some other type + :param to_check: + :return: + """ + if isinstance(to_check, str) and to_check == "": + raise ValueError + elif not isinstance(to_check, str) or to_check is None: + raise TypeError + + def __check_location_coordinates(self, location_to_check): + """ + Check the location to make sure that it has both x and y parts, then checks that both x and y can be converted + into doubles. + :param location_to_check: + :return: + """ + if 'x' not in location_to_check or 'y' not in location_to_check: + raise KeyError + + float(location_to_check['x']) + float(location_to_check['y']) diff --git a/ConfigReader/NodeTester.py b/ConfigReader/NodeTester.py new file mode 100644 index 0000000..34c055f --- /dev/null +++ b/ConfigReader/NodeTester.py @@ -0,0 +1,216 @@ +import unittest +from Node import Node + + +class NodeTestCases(unittest.TestCase): + """ + Tests were created to test the Node class + """ + + def test_power_id_none(self): + """ + Create a power id that is None, should throw an error + :return: + """ + with self.assertRaises(TypeError): + node = Node(None, "test", {"x": "123", "y": "321"}) + + def test_power_id_empty(self): + """ + Create a power id that is an empty string, should throw an error + :return: + """ + with self.assertRaises(ValueError): + node = Node("", "test", {"x": "123", "y": "321"}) + + def test_power_id_type(self): + """ + Create a non-empty and non-None power id, should not throw an error + :return: + """ + with self.assertRaises(TypeError): + node = Node(1, "test", {"x": "123", "y": "321"}) + + def test_network_id_none(self): + """ + Create a network id that is None, should throw an error + :return: + """ + with self.assertRaises(TypeError): + node = Node("test", None, {"x": "123", "y": "321"}) + + def test_network_id_empty(self): + """ + Create a network id that is an empty string, should throw an error + :return: + """ + with self.assertRaises(ValueError): + node = Node("test", "", {"x": "123", "y": "321"}) + + def test_network_id_type(self): + """ + Create a non-empty and non-None network id, should not throw an error + :return: + """ + with self.assertRaises(TypeError): + node = Node("test", 1, {"x": "123", "y": "321"}) + + def test_missing_location_x(self): + """ + Create a location with the x missing, should throw an error + :return: + """ + with self.assertRaises(KeyError): + node = Node("test", "test", {"y", "123"}) + + def test_missing_location_y(self): + """ + Create a location with the y missing, should throw an error + :return: + """ + with self.assertRaises(KeyError): + node = Node("test", "test", {"x": "123"}) + + def test_non_num_location_x(self): + """ + Create a non num location for x in node location, should throw an error + :return: + """ + with self.assertRaises(ValueError): + node = Node("test", "test", {"x": "a", "y": "123.1"}) + + def test_non_num_location_y(self): + """ + Create a non num location for y in node location, should throw an error + :return: + """ + with self.assertRaises(ValueError): + node = Node("test", "test", {"x": "321", "y": "b"}) + + def test_none_location_x(self): + """ + Create a none location for x in node location, should throw an error + :return: + """ + with self.assertRaises(TypeError): + node = Node("test", "test", {"x": None, "y": "123"}) + + def test_none_location_y(self): + """ + Create a none location for y in node location, should throw an error + :return: + """ + with self.assertRaises(TypeError): + node = Node("test", "test", {"x": "321", "y": None}) + + def test_power_id_none_set_attr(self): + """ + Create a power id that is None, should throw an error + :return: + """ + with self.assertRaises(TypeError): + node = Node("test", "test", {"x": "123", "y": "321"}) + node.power_id = None + + def test_power_id_empty_set_attr(self): + """ + Create a power id that is an empty string, should throw an error + :return: + """ + with self.assertRaises(ValueError): + node = Node("test", "test", {"x": "123", "y": "321"}) + node.power_id = "" + + def test_power_id_type_set_attr(self): + """ + Create a non-empty and non-None power id, should not throw an error + :return: + """ + with self.assertRaises(TypeError): + node = Node("test", "test", {"x": "123", "y": "321"}) + node.power_id = 1 + + def test_network_id_none_set_attr(self): + """ + Create a network id that is None, should throw an error + :return: + """ + with self.assertRaises(TypeError): + node = Node("test", "test", {"x": "123", "y": "321"}) + node.network_id = None + + def test_network_id_empty_set_attr(self): + """ + Create a network id that is an empty string, should throw an error + :return: + """ + with self.assertRaises(ValueError): + node = Node("test", "test", {"x": "123", "y": "321"}) + node.network_id = "" + + def test_network_id_type_set_attr(self): + """ + Create a non-empty and non-None network id, should not throw an error + :return: + """ + with self.assertRaises(TypeError): + node = Node("test", "test", {"x": "123", "y": "321"}) + node.network_id = 1 + + def test_missing_location_x_set_attr(self): + """ + Create a location with the x missing, should throw an error + :return: + """ + with self.assertRaises(KeyError): + node = Node("test", "test", {"x": "123", "y": "321"}) + node.location = {"y": "321"} + + def test_missing_location_y_set_attr(self): + """ + Create a location with the y missing, should throw an error + :return: + """ + with self.assertRaises(KeyError): + node = Node("test", "test", {"x": "123", "y": "321"}) + node.location = {"x": "321"} + + def test_non_num_location_x_set_attr(self): + """ + Create a non num location for x in node location, should throw an error + :return: + """ + with self.assertRaises(ValueError): + node = Node("test", "test", {"x": "123", "y": "321"}) + node.location = {"x": "x", "y": "321"} + + def test_non_num_location_y_set_attr(self): + """ + Create a non num location for y in node location, should throw an error + :return: + """ + with self.assertRaises(ValueError): + node = Node("test", "test", {"x": "123", "y": "321"}) + node.location = {"x": "123", "y": "y"} + + def test_none_location_x_set_attr(self): + """ + Create a none location for x in node location, should throw an error + :return: + """ + with self.assertRaises(TypeError): + node = Node("test", "test", {"x": "123", "y": "321"}) + node.location = {"x": None, "y": "123"} + + def test_none_location_y_set_attr(self): + """ + Create a none location for y in node location, should throw an error + :return: + """ + with self.assertRaises(TypeError): + node = Node("test", "test", {"x": "123", "y": "321"}) + node.location = {"x": "123", "y": None} + + +if __name__ == '__main__': + unittest.main() From 5106ea3c645eb7618c7bff2658f495bb2bfbc2f6 Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Thu, 30 Jul 2020 19:27:16 -0600 Subject: [PATCH 10/22] Node and NodeTests updated to reflect immutable nature of Node and nic_type and access_point added - Node is now immutable, none of the member values can be changed, easier to perform validation - NIC type added, network interface type added, this can also be none - Access point added in case NIC is wifi - Started on NetworConnection --- ConfigReader/ConfigDecoder.py | 7 ++ ConfigReader/ConfigErrors.py | 21 +++++ ConfigReader/ConfigReader.py | 21 ++++- ConfigReader/NetworkConnection.py | 9 ++ ConfigReader/Node.py | 46 ++++++++--- ConfigReader/NodeTester.py | 109 ++++--------------------- TapControl/tapcontrol/data/ieee13.json | 2 +- 7 files changed, 108 insertions(+), 107 deletions(-) create mode 100644 ConfigReader/ConfigDecoder.py create mode 100644 ConfigReader/ConfigErrors.py create mode 100644 ConfigReader/NetworkConnection.py diff --git a/ConfigReader/ConfigDecoder.py b/ConfigReader/ConfigDecoder.py new file mode 100644 index 0000000..d6461d7 --- /dev/null +++ b/ConfigReader/ConfigDecoder.py @@ -0,0 +1,7 @@ +from json import JSONDecoder + + +class NodeDecoder(JSONDecoder): + """ + Class was created to decode + """ \ No newline at end of file diff --git a/ConfigReader/ConfigErrors.py b/ConfigReader/ConfigErrors.py new file mode 100644 index 0000000..04fb241 --- /dev/null +++ b/ConfigReader/ConfigErrors.py @@ -0,0 +1,21 @@ +""" +File was created to store all the errors created for Config reading +""" + + +class ImmutableObjectError(Exception): + """Raised when an Immutable object is being edited""" + pass + + +class InvalidNICType(Exception): + """Raised when an invalid type of NIC is passed in""" + pass + + +class InvalidAccessPointValueForNICType(Exception): + """Raised when: + - the value of access point is None or not a bool if NIC is of type wifi + - the value of access point in not None when the NIC is not wifi + """ + pass diff --git a/ConfigReader/ConfigReader.py b/ConfigReader/ConfigReader.py index ca51f45..67e59d5 100644 --- a/ConfigReader/ConfigReader.py +++ b/ConfigReader/ConfigReader.py @@ -6,8 +6,6 @@ class ConfigReader: Class was created to read the config file passed in. This is done so that the file is only read once and then the data can be passed to each simulator without having to read the file again. """ - file = "" - def __init__(self, file): """ The initializer, saves the file pointer passed in. Since the setting of file starts reading the file, this will @@ -15,3 +13,22 @@ def __init__(self, file): :param file: """ self.file = file + + def __setattr__(self, key, value): + """ + Modified to start reading the file once file has been set + :param key: + :param value: + :return: + """ + # Call the writer like normal + super(ConfigReader, self).__setattr__(key, value) + # Now call the method that will read the file if file was changed + if key == 'file': + self.__read_file() + + def __read_file(self): + """ + Method reads the file pointer that has been stored as the member + :return: + """ diff --git a/ConfigReader/NetworkConnection.py b/ConfigReader/NetworkConnection.py new file mode 100644 index 0000000..511884f --- /dev/null +++ b/ConfigReader/NetworkConnection.py @@ -0,0 +1,9 @@ +from ConfigErrors import ImmutableObjectError + + +class NetworkConnection: + """ + Class was created to store the network connections. This includes connections between machines, but not connections + between applications, ie Server/Client connections will not be stored here. + """ + diff --git a/ConfigReader/Node.py b/ConfigReader/Node.py index b48f14e..a96293f 100644 --- a/ConfigReader/Node.py +++ b/ConfigReader/Node.py @@ -1,15 +1,24 @@ +from ConfigErrors import ImmutableObjectError, InvalidNICType, InvalidAccessPointValueForNICType + + class Node: """ Class was created to store the information on a node. Solely meant to be used by ConfigReader """ + # Stores the valid types + __valid_nic_types = ["wifi", "p2p", None] # Stores the id of the node in the power system power_id = "" # Stores the id of the node in the network network_id = "" # Stores the network of the system location = {} + # Stores the NIC card type + nic_type = "" + # If this network card is a wifi card, then this will be used + access_point = False - def __init__(self, power_id, network_id, location): + def __init__(self, power_id, network_id, location, nic_type=None, access_point=None): """ Validates that all the data necessary is present and is of the correct type and then saves it :param power_id: @@ -19,26 +28,39 @@ def __init__(self, power_id, network_id, location): self.__check_power_id_type(power_id) self.__check_network_id_type(network_id) self.__check_location_coordinates(location) + self.__check_network_card_type_and_access_point_value(nic_type, access_point) - self.power_id = power_id - self.network_id = network_id - self.location = location + super(Node, self).__setattr__('power_id', power_id) + super(Node, self).__setattr__('network_id', network_id) + super(Node, self).__setattr__('location', location) + super(Node, self).__setattr__('nic_type', nic_type) + super(Node, self).__setattr__('access_point', access_point) def __setattr__(self, key, value): """ - Overridden to check that the value being set to the members is correct before writing it + Overridden to ensure that nothing in the class is mutable after creation :param key: :param value: :return: """ - if key == "power_id": - self.__check_power_id_type(value) - elif key == "network_id": - self.__check_network_id_type(value) - elif key == "location": - self.__check_location_coordinates(value) + raise ImmutableObjectError - super(Node, self).__setattr__(key, value) + def __check_network_card_type_and_access_point_value(self, network_card_type, access_point): + """ + Checks the value of network card type, if it is of type wifi or p2p, then check access point value. If type of + NIC is wifi, then access_point should not be None, otherwise it should be None + :param network_card_type: + :param access_point: + :return: + """ + if not network_card_type in self.__valid_nic_types: + raise InvalidNICType + elif network_card_type != "wifi" and access_point is not None: + raise InvalidAccessPointValueForNICType + elif network_card_type == "wifi": + # Check to make sure access_point is not None and is a bool + if access_point is None or not isinstance(access_point, bool): + raise InvalidAccessPointValueForNICType def __check_power_id_type(self, power_id): """ diff --git a/ConfigReader/NodeTester.py b/ConfigReader/NodeTester.py index 34c055f..7ad5e6b 100644 --- a/ConfigReader/NodeTester.py +++ b/ConfigReader/NodeTester.py @@ -1,5 +1,7 @@ import unittest + from Node import Node +from ConfigErrors import ImmutableObjectError, InvalidNICType, InvalidAccessPointValueForNICType class NodeTestCases(unittest.TestCase): @@ -103,113 +105,36 @@ def test_none_location_y(self): with self.assertRaises(TypeError): node = Node("test", "test", {"x": "321", "y": None}) - def test_power_id_none_set_attr(self): + def test_invalid_nic_type(self): """ - Create a power id that is None, should throw an error + Create a node with an invalid type of nic :return: """ - with self.assertRaises(TypeError): - node = Node("test", "test", {"x": "123", "y": "321"}) - node.power_id = None + with self.assertRaises(InvalidNICType): + node = Node("test", "test", {"x": "321", "y": "123"}, nic_type="not_valid") - def test_power_id_empty_set_attr(self): + def test_none_nic_type(self): """ - Create a power id that is an empty string, should throw an error + Create a node with a None nic card, should not raise an error :return: """ - with self.assertRaises(ValueError): - node = Node("test", "test", {"x": "123", "y": "321"}) - node.power_id = "" + node = Node("test", "test", {"x": "321", "y": "123"}) - def test_power_id_type_set_attr(self): + def test_nic_wifi_with_none_access_point(self): """ - Create a non-empty and non-None power id, should not throw an error + Create a node with a wifi nic card, but no access point value passed in :return: """ - with self.assertRaises(TypeError): - node = Node("test", "test", {"x": "123", "y": "321"}) - node.power_id = 1 + with self.assertRaises(InvalidAccessPointValueForNICType): + node = Node("test", "test", {"x": "321", "y": "123"}, nic_type="wifi") - def test_network_id_none_set_attr(self): + def test_nic_p2p_with_access_point(self): """ - Create a network id that is None, should throw an error + Create a node with a p2p nic card, but with an access point value :return: """ - with self.assertRaises(TypeError): - node = Node("test", "test", {"x": "123", "y": "321"}) - node.network_id = None - - def test_network_id_empty_set_attr(self): - """ - Create a network id that is an empty string, should throw an error - :return: - """ - with self.assertRaises(ValueError): - node = Node("test", "test", {"x": "123", "y": "321"}) - node.network_id = "" - - def test_network_id_type_set_attr(self): - """ - Create a non-empty and non-None network id, should not throw an error - :return: - """ - with self.assertRaises(TypeError): - node = Node("test", "test", {"x": "123", "y": "321"}) - node.network_id = 1 - - def test_missing_location_x_set_attr(self): - """ - Create a location with the x missing, should throw an error - :return: - """ - with self.assertRaises(KeyError): - node = Node("test", "test", {"x": "123", "y": "321"}) - node.location = {"y": "321"} - - def test_missing_location_y_set_attr(self): - """ - Create a location with the y missing, should throw an error - :return: - """ - with self.assertRaises(KeyError): - node = Node("test", "test", {"x": "123", "y": "321"}) - node.location = {"x": "321"} - - def test_non_num_location_x_set_attr(self): - """ - Create a non num location for x in node location, should throw an error - :return: - """ - with self.assertRaises(ValueError): - node = Node("test", "test", {"x": "123", "y": "321"}) - node.location = {"x": "x", "y": "321"} - - def test_non_num_location_y_set_attr(self): - """ - Create a non num location for y in node location, should throw an error - :return: - """ - with self.assertRaises(ValueError): - node = Node("test", "test", {"x": "123", "y": "321"}) - node.location = {"x": "123", "y": "y"} - - def test_none_location_x_set_attr(self): - """ - Create a none location for x in node location, should throw an error - :return: - """ - with self.assertRaises(TypeError): - node = Node("test", "test", {"x": "123", "y": "321"}) - node.location = {"x": None, "y": "123"} - - def test_none_location_y_set_attr(self): - """ - Create a none location for y in node location, should throw an error - :return: - """ - with self.assertRaises(TypeError): - node = Node("test", "test", {"x": "123", "y": "321"}) - node.location = {"x": "123", "y": None} + with self.assertRaises(InvalidAccessPointValueForNICType): + node = Node("test", "test", {"x": "321", "y": "123"}, nic_type="p2p", access_point=False) if __name__ == '__main__': diff --git a/TapControl/tapcontrol/data/ieee13.json b/TapControl/tapcontrol/data/ieee13.json index 753639e..eb2937d 100644 --- a/TapControl/tapcontrol/data/ieee13.json +++ b/TapControl/tapcontrol/data/ieee13.json @@ -259,4 +259,4 @@ "client_type": "sensor" } ] -} \ No newline at end of file +} From 65b84d0539bf05c80333b49e2b03dbe2955785b8 Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Thu, 30 Jul 2020 19:54:06 -0600 Subject: [PATCH 11/22] Node Updated - Node has been updated to store multiple types of NICs - Node test cases have been updated - Validation functions have been moved out of Node and into their own file --- ConfigReader/ConfigDecoder.py | 7 --- ConfigReader/NetworkConnection.py | 9 +++ ConfigReader/NetworkConnectionTestCases.py | 10 ++++ ConfigReader/Node.py | 58 ++++--------------- .../{NodeTester.py => NodeTestCases.py} | 6 +- ConfigReader/ValidationFunctions.py | 49 ++++++++++++++++ 6 files changed, 81 insertions(+), 58 deletions(-) delete mode 100644 ConfigReader/ConfigDecoder.py create mode 100644 ConfigReader/NetworkConnectionTestCases.py rename ConfigReader/{NodeTester.py => NodeTestCases.py} (98%) create mode 100644 ConfigReader/ValidationFunctions.py diff --git a/ConfigReader/ConfigDecoder.py b/ConfigReader/ConfigDecoder.py deleted file mode 100644 index d6461d7..0000000 --- a/ConfigReader/ConfigDecoder.py +++ /dev/null @@ -1,7 +0,0 @@ -from json import JSONDecoder - - -class NodeDecoder(JSONDecoder): - """ - Class was created to decode - """ \ No newline at end of file diff --git a/ConfigReader/NetworkConnection.py b/ConfigReader/NetworkConnection.py index 511884f..3d1bea1 100644 --- a/ConfigReader/NetworkConnection.py +++ b/ConfigReader/NetworkConnection.py @@ -6,4 +6,13 @@ class NetworkConnection: Class was created to store the network connections. This includes connections between machines, but not connections between applications, ie Server/Client connections will not be stored here. """ + def __init__(self, nodes): + def __setattr__(self, key, value): + """ + Overridden to ensure that nothing in the class is mutable after creation + :param key: + :param value: + :return: + """ + raise ImmutableObjectError \ No newline at end of file diff --git a/ConfigReader/NetworkConnectionTestCases.py b/ConfigReader/NetworkConnectionTestCases.py new file mode 100644 index 0000000..ea6b18d --- /dev/null +++ b/ConfigReader/NetworkConnectionTestCases.py @@ -0,0 +1,10 @@ +import unittest + + +class NetworkConnectionTestCases(unittest.TestCase): + def test_something(self): + self.assertEqual(True, False) + + +if __name__ == '__main__': + unittest.main() diff --git a/ConfigReader/Node.py b/ConfigReader/Node.py index a96293f..a8fe9c8 100644 --- a/ConfigReader/Node.py +++ b/ConfigReader/Node.py @@ -1,4 +1,6 @@ -from ConfigErrors import ImmutableObjectError, InvalidNICType, InvalidAccessPointValueForNICType +from ConfigErrors import ImmutableObjectError +from ValidationFunctions import check_location_coordinates, check_network_card_type_and_access_point_value, \ + check_non_empty_non_none_string class Node: @@ -14,11 +16,11 @@ class Node: # Stores the network of the system location = {} # Stores the NIC card type - nic_type = "" + nic_types = [] # If this network card is a wifi card, then this will be used access_point = False - def __init__(self, power_id, network_id, location, nic_type=None, access_point=None): + def __init__(self, power_id, network_id, location, nic_types=[None], access_point=None): """ Validates that all the data necessary is present and is of the correct type and then saves it :param power_id: @@ -27,13 +29,13 @@ def __init__(self, power_id, network_id, location, nic_type=None, access_point=N """ self.__check_power_id_type(power_id) self.__check_network_id_type(network_id) - self.__check_location_coordinates(location) - self.__check_network_card_type_and_access_point_value(nic_type, access_point) + check_location_coordinates(location) + check_network_card_type_and_access_point_value(nic_types, access_point, self.__valid_nic_types) super(Node, self).__setattr__('power_id', power_id) super(Node, self).__setattr__('network_id', network_id) super(Node, self).__setattr__('location', location) - super(Node, self).__setattr__('nic_type', nic_type) + super(Node, self).__setattr__('nic_types', nic_types) super(Node, self).__setattr__('access_point', access_point) def __setattr__(self, key, value): @@ -45,30 +47,13 @@ def __setattr__(self, key, value): """ raise ImmutableObjectError - def __check_network_card_type_and_access_point_value(self, network_card_type, access_point): - """ - Checks the value of network card type, if it is of type wifi or p2p, then check access point value. If type of - NIC is wifi, then access_point should not be None, otherwise it should be None - :param network_card_type: - :param access_point: - :return: - """ - if not network_card_type in self.__valid_nic_types: - raise InvalidNICType - elif network_card_type != "wifi" and access_point is not None: - raise InvalidAccessPointValueForNICType - elif network_card_type == "wifi": - # Check to make sure access_point is not None and is a bool - if access_point is None or not isinstance(access_point, bool): - raise InvalidAccessPointValueForNICType - def __check_power_id_type(self, power_id): """ Checks that the power id passed in is a non-empty string. :param power_id: :return: """ - self.__check_non_empty_non_none_string(power_id) + check_non_empty_non_none_string(power_id) def __check_network_id_type(self, network_id): """ @@ -76,28 +61,5 @@ def __check_network_id_type(self, network_id): :param network_id: :return: """ - self.__check_non_empty_non_none_string(network_id) - - def __check_non_empty_non_none_string(self, to_check): - """ - Created to check that to_check is not None, is not an empty string and is not of some other type - :param to_check: - :return: - """ - if isinstance(to_check, str) and to_check == "": - raise ValueError - elif not isinstance(to_check, str) or to_check is None: - raise TypeError - - def __check_location_coordinates(self, location_to_check): - """ - Check the location to make sure that it has both x and y parts, then checks that both x and y can be converted - into doubles. - :param location_to_check: - :return: - """ - if 'x' not in location_to_check or 'y' not in location_to_check: - raise KeyError + check_non_empty_non_none_string(network_id) - float(location_to_check['x']) - float(location_to_check['y']) diff --git a/ConfigReader/NodeTester.py b/ConfigReader/NodeTestCases.py similarity index 98% rename from ConfigReader/NodeTester.py rename to ConfigReader/NodeTestCases.py index 7ad5e6b..bc52d60 100644 --- a/ConfigReader/NodeTester.py +++ b/ConfigReader/NodeTestCases.py @@ -111,7 +111,7 @@ def test_invalid_nic_type(self): :return: """ with self.assertRaises(InvalidNICType): - node = Node("test", "test", {"x": "321", "y": "123"}, nic_type="not_valid") + node = Node("test", "test", {"x": "321", "y": "123"}, nic_types=["not_valid"]) def test_none_nic_type(self): """ @@ -126,7 +126,7 @@ def test_nic_wifi_with_none_access_point(self): :return: """ with self.assertRaises(InvalidAccessPointValueForNICType): - node = Node("test", "test", {"x": "321", "y": "123"}, nic_type="wifi") + node = Node("test", "test", {"x": "321", "y": "123"}, nic_types=["wifi"]) def test_nic_p2p_with_access_point(self): """ @@ -134,7 +134,7 @@ def test_nic_p2p_with_access_point(self): :return: """ with self.assertRaises(InvalidAccessPointValueForNICType): - node = Node("test", "test", {"x": "321", "y": "123"}, nic_type="p2p", access_point=False) + node = Node("test", "test", {"x": "321", "y": "123"}, nic_types=["p2p"], access_point=False) if __name__ == '__main__': diff --git a/ConfigReader/ValidationFunctions.py b/ConfigReader/ValidationFunctions.py new file mode 100644 index 0000000..67a8d90 --- /dev/null +++ b/ConfigReader/ValidationFunctions.py @@ -0,0 +1,49 @@ +""" +File contains all the validation tests needed to make sure the values stored in the Classes are valid. +""" +from ConfigErrors import InvalidNICType, InvalidAccessPointValueForNICType + + +def check_non_empty_non_none_string(to_check): + """ + Created to check that to_check is not None, is not an empty string and is not of some other type + :param to_check: + :return: + """ + if isinstance(to_check, str) and to_check == "": + raise ValueError + elif not isinstance(to_check, str) or to_check is None: + raise TypeError + + +def check_location_coordinates(location_to_check): + """ + Check the location to make sure that it has both x and y parts, then checks that both x and y can be converted + into doubles. + :param location_to_check: + :return: + """ + if 'x' not in location_to_check or 'y' not in location_to_check: + raise KeyError + + float(location_to_check['x']) + float(location_to_check['y']) + + +def check_network_card_type_and_access_point_value(network_card_types, access_point, valid_nic_types): + """ + Checks the value of network card type, if it is of type wifi or p2p, then check access point value. If type of + NIC is wifi, then access_point should not be None, otherwise it should be None + :param network_card_type: + :param access_point: + :param valid_nic_types: + :return: + """ + if len(set(network_card_types).intersection(set(valid_nic_types))) != len(network_card_types): + raise InvalidNICType + elif "wifi" not in network_card_types and access_point is not None: + raise InvalidAccessPointValueForNICType + elif "wifi" in network_card_types: + # Check to make sure access_point is not None and is a bool + if access_point is None or not isinstance(access_point, bool): + raise InvalidAccessPointValueForNICType \ No newline at end of file From 4f836900b832224c4f9b512ebab28444b5cd27d1 Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Thu, 30 Jul 2020 20:36:32 -0600 Subject: [PATCH 12/22] Network Connection Done and validation code moved - Network Connection class finished - Network Connection class is immutable - Network Connection class has been tested using the tests created. - More validation code has been moved to Valication Functions and more validation functions have been created to validate NetworkConnections --- ConfigReader/ConfigErrors.py | 13 ++- ConfigReader/NetworkConnection.py | 21 +++- ConfigReader/NetworkConnectionTestCases.py | 59 +++++++++- ConfigReader/Node.py | 6 +- ConfigReader/NodeTestCases.py | 41 +++---- ConfigReader/ValidationFunctions.py | 42 ++++++- TapControl/tapcontrol/data/ieee13.json | 124 ++++++++++++--------- 7 files changed, 215 insertions(+), 91 deletions(-) diff --git a/ConfigReader/ConfigErrors.py b/ConfigReader/ConfigErrors.py index 04fb241..3ae27e1 100644 --- a/ConfigReader/ConfigErrors.py +++ b/ConfigReader/ConfigErrors.py @@ -8,7 +8,7 @@ class ImmutableObjectError(Exception): pass -class InvalidNICType(Exception): +class InvalidNetworkType(Exception): """Raised when an invalid type of NIC is passed in""" pass @@ -19,3 +19,14 @@ class InvalidAccessPointValueForNICType(Exception): - the value of access point in not None when the NIC is not wifi """ pass + + +class NetworkConnectionNumberOfNodesNotCorrect(Exception): + """Raised when a network connection does not have 2 nodes passed in.""" + pass + + +class NetworkConnectionHasNodesWithConnectionToSelf(Exception): + """Raised when a node is connected to itself in the network connection.""" + pass + diff --git a/ConfigReader/NetworkConnection.py b/ConfigReader/NetworkConnection.py index 3d1bea1..4059d2b 100644 --- a/ConfigReader/NetworkConnection.py +++ b/ConfigReader/NetworkConnection.py @@ -1,4 +1,5 @@ from ConfigErrors import ImmutableObjectError +from ValidationFunctions import check_network_connection_nodes, check_network_connection_type class NetworkConnection: @@ -6,7 +7,23 @@ class NetworkConnection: Class was created to store the network connections. This includes connections between machines, but not connections between applications, ie Server/Client connections will not be stored here. """ - def __init__(self, nodes): + # Stores the nodes in the connection + nodes = [] + # Stores the type of connection + conn_type = "" + + def __init__(self, nodes, conn_type): + """ + Validates all the information passed in and stores it within itself. Meaning there should be two nodes passed in + . Each node should be a string, which will be the id of the string + :param nodes: + :param type: + """ + check_network_connection_nodes(nodes) + check_network_connection_type([conn_type]) + + super(NetworkConnection, self).__setattr__('nodes', nodes) + super(NetworkConnection, self).__setattr__('conn_type', conn_type) def __setattr__(self, key, value): """ @@ -15,4 +32,4 @@ def __setattr__(self, key, value): :param value: :return: """ - raise ImmutableObjectError \ No newline at end of file + raise ImmutableObjectError diff --git a/ConfigReader/NetworkConnectionTestCases.py b/ConfigReader/NetworkConnectionTestCases.py index ea6b18d..79af6ce 100644 --- a/ConfigReader/NetworkConnectionTestCases.py +++ b/ConfigReader/NetworkConnectionTestCases.py @@ -1,10 +1,65 @@ import unittest +from ConfigErrors import NetworkConnectionNumberOfNodesNotCorrect, NetworkConnectionHasNodesWithConnectionToSelf, \ + InvalidNetworkType +from NetworkConnection import NetworkConnection class NetworkConnectionTestCases(unittest.TestCase): - def test_something(self): - self.assertEqual(True, False) + """ + Tests were created to test the NetworkConnection class + """ + def test_too_many_nodes(self): + """ + Creates a NetworkConnection with too many nodes, should throw an error + :return: + """ + with self.assertRaises(NetworkConnectionNumberOfNodesNotCorrect): + nc = NetworkConnection(["123", "321", "5432"], "wifi") + def test_too_few_nodes(self): + """ + Create a NetworkConnection with too few nodes, should throw an error + :return: + """ + with self.assertRaises(NetworkConnectionNumberOfNodesNotCorrect): + nc = NetworkConnection(["123", "321", "5432"], "wifi") + + def test_network_connection_to_self(self): + """ + Create a NetworkConnection where a node is connected to itself, should throw an error + :return: + """ + with self.assertRaises(NetworkConnectionHasNodesWithConnectionToSelf): + nc = NetworkConnection(["123", "123"], "wifi") + + def test_correct_number_of_nodes(self): + """ + Creates a NetworkConnection with the correct number of nodes, should not throw an error + :return: + """ + nc = NetworkConnection(["123", "312"], "wifi") + + def test_correct_network_type_wifi(self): + """ + Creates a NetworkConnection with an correct type of network ie, wifi + :return: + """ + nc = NetworkConnection(["123", "321"], "wifi") + + def test_correct_network_type_p2p(self): + """ + Creates a NetworkConnection with an correct type of network ie, p2p + :return: + """ + nc = NetworkConnection(["123", "321"], "p2p") + + def test_incorrect_network_type(self): + """ + Creates a NetworkConnection with an incorrect type of network ie, not wifi and not p2p, should throw an error + :return: + """ + with self.assertRaises(InvalidNetworkType): + nc = NetworkConnection(["123", "321"], "some") if __name__ == '__main__': unittest.main() diff --git a/ConfigReader/Node.py b/ConfigReader/Node.py index a8fe9c8..922616e 100644 --- a/ConfigReader/Node.py +++ b/ConfigReader/Node.py @@ -7,8 +7,6 @@ class Node: """ Class was created to store the information on a node. Solely meant to be used by ConfigReader """ - # Stores the valid types - __valid_nic_types = ["wifi", "p2p", None] # Stores the id of the node in the power system power_id = "" # Stores the id of the node in the network @@ -20,7 +18,7 @@ class Node: # If this network card is a wifi card, then this will be used access_point = False - def __init__(self, power_id, network_id, location, nic_types=[None], access_point=None): + def __init__(self, power_id, network_id, location, nic_types, access_point=None): """ Validates that all the data necessary is present and is of the correct type and then saves it :param power_id: @@ -30,7 +28,7 @@ def __init__(self, power_id, network_id, location, nic_types=[None], access_poin self.__check_power_id_type(power_id) self.__check_network_id_type(network_id) check_location_coordinates(location) - check_network_card_type_and_access_point_value(nic_types, access_point, self.__valid_nic_types) + check_network_card_type_and_access_point_value(nic_types, access_point) super(Node, self).__setattr__('power_id', power_id) super(Node, self).__setattr__('network_id', network_id) diff --git a/ConfigReader/NodeTestCases.py b/ConfigReader/NodeTestCases.py index bc52d60..813e562 100644 --- a/ConfigReader/NodeTestCases.py +++ b/ConfigReader/NodeTestCases.py @@ -1,7 +1,7 @@ import unittest from Node import Node -from ConfigErrors import ImmutableObjectError, InvalidNICType, InvalidAccessPointValueForNICType +from ConfigErrors import ImmutableObjectError, InvalidNetworkType, InvalidAccessPointValueForNICType class NodeTestCases(unittest.TestCase): @@ -15,7 +15,7 @@ def test_power_id_none(self): :return: """ with self.assertRaises(TypeError): - node = Node(None, "test", {"x": "123", "y": "321"}) + node = Node(None, "test", {"x": "123", "y": "321"}, ["p2p"]) def test_power_id_empty(self): """ @@ -23,7 +23,7 @@ def test_power_id_empty(self): :return: """ with self.assertRaises(ValueError): - node = Node("", "test", {"x": "123", "y": "321"}) + node = Node("", "test", {"x": "123", "y": "321"}, ["p2p"]) def test_power_id_type(self): """ @@ -31,7 +31,7 @@ def test_power_id_type(self): :return: """ with self.assertRaises(TypeError): - node = Node(1, "test", {"x": "123", "y": "321"}) + node = Node(1, "test", {"x": "123", "y": "321"}, ["p2p"]) def test_network_id_none(self): """ @@ -39,7 +39,7 @@ def test_network_id_none(self): :return: """ with self.assertRaises(TypeError): - node = Node("test", None, {"x": "123", "y": "321"}) + node = Node("test", None, {"x": "123", "y": "321"}, ["p2p"]) def test_network_id_empty(self): """ @@ -47,7 +47,7 @@ def test_network_id_empty(self): :return: """ with self.assertRaises(ValueError): - node = Node("test", "", {"x": "123", "y": "321"}) + node = Node("test", "", {"x": "123", "y": "321"}, ["p2p"]) def test_network_id_type(self): """ @@ -55,7 +55,7 @@ def test_network_id_type(self): :return: """ with self.assertRaises(TypeError): - node = Node("test", 1, {"x": "123", "y": "321"}) + node = Node("test", 1, {"x": "123", "y": "321"}, ["p2p"]) def test_missing_location_x(self): """ @@ -63,7 +63,7 @@ def test_missing_location_x(self): :return: """ with self.assertRaises(KeyError): - node = Node("test", "test", {"y", "123"}) + node = Node("test", "test", {"y", "123"}, ["p2p"]) def test_missing_location_y(self): """ @@ -71,7 +71,7 @@ def test_missing_location_y(self): :return: """ with self.assertRaises(KeyError): - node = Node("test", "test", {"x": "123"}) + node = Node("test", "test", {"x": "123"}, ["p2p"]) def test_non_num_location_x(self): """ @@ -79,7 +79,7 @@ def test_non_num_location_x(self): :return: """ with self.assertRaises(ValueError): - node = Node("test", "test", {"x": "a", "y": "123.1"}) + node = Node("test", "test", {"x": "a", "y": "123.1"}, ["p2p"]) def test_non_num_location_y(self): """ @@ -87,7 +87,7 @@ def test_non_num_location_y(self): :return: """ with self.assertRaises(ValueError): - node = Node("test", "test", {"x": "321", "y": "b"}) + node = Node("test", "test", {"x": "321", "y": "b"}, ["p2p"]) def test_none_location_x(self): """ @@ -95,7 +95,7 @@ def test_none_location_x(self): :return: """ with self.assertRaises(TypeError): - node = Node("test", "test", {"x": None, "y": "123"}) + node = Node("test", "test", {"x": None, "y": "123"}, ["p2p"]) def test_none_location_y(self): """ @@ -103,22 +103,15 @@ def test_none_location_y(self): :return: """ with self.assertRaises(TypeError): - node = Node("test", "test", {"x": "321", "y": None}) + node = Node("test", "test", {"x": "321", "y": None}, ["p2p"]) def test_invalid_nic_type(self): """ Create a node with an invalid type of nic :return: """ - with self.assertRaises(InvalidNICType): - node = Node("test", "test", {"x": "321", "y": "123"}, nic_types=["not_valid"]) - - def test_none_nic_type(self): - """ - Create a node with a None nic card, should not raise an error - :return: - """ - node = Node("test", "test", {"x": "321", "y": "123"}) + with self.assertRaises(InvalidNetworkType): + node = Node("test", "test", {"x": "321", "y": "123"}, ["not_valid"]) def test_nic_wifi_with_none_access_point(self): """ @@ -126,7 +119,7 @@ def test_nic_wifi_with_none_access_point(self): :return: """ with self.assertRaises(InvalidAccessPointValueForNICType): - node = Node("test", "test", {"x": "321", "y": "123"}, nic_types=["wifi"]) + node = Node("test", "test", {"x": "321", "y": "123"}, ["wifi"]) def test_nic_p2p_with_access_point(self): """ @@ -134,7 +127,7 @@ def test_nic_p2p_with_access_point(self): :return: """ with self.assertRaises(InvalidAccessPointValueForNICType): - node = Node("test", "test", {"x": "321", "y": "123"}, nic_types=["p2p"], access_point=False) + node = Node("test", "test", {"x": "321", "y": "123"}, ["p2p"], access_point=False) if __name__ == '__main__': diff --git a/ConfigReader/ValidationFunctions.py b/ConfigReader/ValidationFunctions.py index 67a8d90..3edfccc 100644 --- a/ConfigReader/ValidationFunctions.py +++ b/ConfigReader/ValidationFunctions.py @@ -1,8 +1,11 @@ """ File contains all the validation tests needed to make sure the values stored in the Classes are valid. """ -from ConfigErrors import InvalidNICType, InvalidAccessPointValueForNICType +from ConfigErrors import InvalidNetworkType, InvalidAccessPointValueForNICType, \ + NetworkConnectionNumberOfNodesNotCorrect, NetworkConnectionHasNodesWithConnectionToSelf +# Stores the valid types of nics +valid_nic_types = ["wifi", "p2p"] def check_non_empty_non_none_string(to_check): """ @@ -30,7 +33,7 @@ def check_location_coordinates(location_to_check): float(location_to_check['y']) -def check_network_card_type_and_access_point_value(network_card_types, access_point, valid_nic_types): +def check_network_card_type_and_access_point_value(network_card_types, access_point): """ Checks the value of network card type, if it is of type wifi or p2p, then check access point value. If type of NIC is wifi, then access_point should not be None, otherwise it should be None @@ -39,11 +42,38 @@ def check_network_card_type_and_access_point_value(network_card_types, access_po :param valid_nic_types: :return: """ - if len(set(network_card_types).intersection(set(valid_nic_types))) != len(network_card_types): - raise InvalidNICType - elif "wifi" not in network_card_types and access_point is not None: + check_network_connection_type(network_card_types) + + if "wifi" not in network_card_types and access_point is not None: raise InvalidAccessPointValueForNICType elif "wifi" in network_card_types: # Check to make sure access_point is not None and is a bool if access_point is None or not isinstance(access_point, bool): - raise InvalidAccessPointValueForNICType \ No newline at end of file + raise InvalidAccessPointValueForNICType + + +def check_network_connection_type(network_connection_type): + """ + Check to see if the network connection type is of a valid type. + :param network_connection_type: + :return: + """ + if len(set(network_connection_type).intersection(set(valid_nic_types))) != len(network_connection_type): + raise InvalidNetworkType + +def check_network_connection_nodes(nodes): + """ + Method checks to make sure there are only two nodes passed into the connection. Also checks to make sure that each + node is valid using check_non_empty_non_none_string. + :param nodes: + :return: + """ + if len(nodes) != 2: + raise NetworkConnectionNumberOfNodesNotCorrect + + if len(set(nodes)) != len(nodes): + raise NetworkConnectionHasNodesWithConnectionToSelf + + # Now make sure every node is valid + for node in nodes: + check_non_empty_non_none_string(node) diff --git a/TapControl/tapcontrol/data/ieee13.json b/TapControl/tapcontrol/data/ieee13.json index eb2937d..15927cd 100644 --- a/TapControl/tapcontrol/data/ieee13.json +++ b/TapControl/tapcontrol/data/ieee13.json @@ -7,7 +7,8 @@ "location": { "x": "200", "y": "400" - } + }, + "nic_card_types": ["p2p"] }, { "id": "1", @@ -15,7 +16,8 @@ "location": { "x": "200", "y": "350" - } + }, + "nic_card_types": ["p2p"] }, { "id": "2", @@ -23,7 +25,8 @@ "location": { "x": "200", "y": "300" - } + }, + "nic_card_types": ["p2p"] }, { "id": "3", @@ -31,7 +34,8 @@ "location": { "x": "0", "y": "250" - } + }, + "nic_card_types": ["p2p"] }, { "id": "4", @@ -39,7 +43,8 @@ "location": { "x": "100", "y": "250" - } + }, + "nic_card_types": ["p2p"] }, { "id": "5", @@ -47,7 +52,9 @@ "location": { "x": "200", "y": "250" - } + }, + "nic_card_types": ["p2p", "wifi"], + "access_point": true }, { "id": "6", @@ -55,7 +62,8 @@ "location": { "x": "350", "y": "250" - } + }, + "nic_card_types": ["p2p"] }, { "id": "7", @@ -63,7 +71,8 @@ "location": { "x": "400", "y": "250" - } + }, + "nic_card_types": ["p2p"] }, { "id": "8", @@ -71,7 +80,8 @@ "location": { "x": "200", "y": "200" - } + }, + "nic_card_types": ["p2p"] }, { "id": "9", @@ -79,7 +89,8 @@ "location": { "x": "0", "y": "100" - } + }, + "nic_card_types": ["p2p"] }, { "id": "10", @@ -87,7 +98,8 @@ "location": { "x": "100", "y": "100" - } + }, + "nic_card_types": ["p2p"] }, { "id": "11", @@ -95,7 +107,8 @@ "location": { "x": "200", "y": "100" - } + }, + "nic_card_types": ["p2p"] }, { "id": "12", @@ -103,7 +116,8 @@ "location": { "x": "250", "y": "100" - } + }, + "nic_card_types": ["p2p"] }, { "id": "13", @@ -111,7 +125,8 @@ "location": { "x": "400", "y": "100" - } + }, + "nic_card_types": ["p2p"] }, { "id": "14", @@ -119,7 +134,8 @@ "location": { "x": "100", "y": "0" - } + }, + "nic_card_types": ["p2p"] }, { "id": "15", @@ -127,69 +143,70 @@ "location": { "x": "200", "y": "0" - } + }, + "nic_card_types": ["p2p"] } ], "network_layout": [ { - "nodes":["0", "1"], - "type": "p2p" + "nodes":["0", "1"], + "type": "p2p" }, { - "nodes":["1", "2"], - "type": "p2p" + "nodes":["1", "2"], + "type": "p2p" }, { - "nodes":["6", "7"], - "type": "p2p" + "nodes":["6", "7"], + "type": "p2p" }, { - "nodes":["10", "11"], - "type": "p2p" + "nodes":["10", "11"], + "type": "p2p" }, { - "nodes":["4", "5"], - "type": "p2p" + "nodes":["4", "5"], + "type": "p2p" }, { - "nodes":["5", "6"], - "type": "p2p" + "nodes":["5", "6"], + "type": "p2p" }, { - "nodes":["8", "11"], - "type": "p2p" + "nodes":["8", "11"], + "type": "p2p" }, { - "nodes":["11", "12"], - "type": "p2p" + "nodes":["11", "12"], + "type": "p2p" }, { - "nodes":["12", "13"], - "type": "p2p" + "nodes":["12", "13"], + "type": "p2p" }, { - "nodes":["9", "10"], - "type": "p2p" + "nodes":["9", "10"], + "type": "p2p" }, { - "nodes":["10", "14"], - "type": "p2p" + "nodes":["10", "14"], + "type": "p2p" }, { - "nodes":["11", "15"], - "type": "p2p" + "nodes":["11", "15"], + "type": "p2p" }, { - "nodes":["2", "5"], - "type": "p2p" + "nodes":["2", "5"], + "type": "p2p" }, { - "nodes":["3", "4"], - "type": "p2p" + "nodes":["3", "4"], + "type": "p2p" }, { - "nodes":["5", "8"], - "type": "p2p" + "nodes":["5", "8"], + "type": "p2p" } ] }, @@ -197,29 +214,32 @@ "nodes": [ { "id": "16", - "access_point": false, "power_network_id": "6321", "location": { "x": "150", "y": "250" - } + }, + "nic_card_types": ["wifi"], + "access_point": false }, { "id": "17", - "access_point": false, "power_network_id": "6322", "location": { "x": "100", "y": "350" - } + }, + "nic_card_types": ["wifi"], + "access_point": false }, { "id": "18", - "access_point": true, "location": { "x": "100", "y": "300" - } + }, + "nic_card_types": ["wifi"], + "access_point": true } ], "network_layout": [ From 996199048ccede1fafb2bf503fae4411f45da151 Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Thu, 30 Jul 2020 20:49:21 -0600 Subject: [PATCH 13/22] Author information added to files. --- ConfigReader/AppConnections.py | 10 ++++++++++ ConfigReader/AppConnectionsTestCases.py | 10 ++++++++++ ConfigReader/ConfigErrors.py | 9 ++++++++- ConfigReader/ConfigReader.py | 12 ++++++++++++ ConfigReader/NetworkConnection.py | 12 ++++++++++++ ConfigReader/NetworkConnectionTestCases.py | 13 +++++++++++++ ConfigReader/Node.py | 12 ++++++++++++ ConfigReader/NodeTestCases.py | 11 +++++++++++ ConfigReader/ValidationFunctions.py | 10 ++++++++++ 9 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 ConfigReader/AppConnections.py create mode 100644 ConfigReader/AppConnectionsTestCases.py diff --git a/ConfigReader/AppConnections.py b/ConfigReader/AppConnections.py new file mode 100644 index 0000000..cd85a94 --- /dev/null +++ b/ConfigReader/AppConnections.py @@ -0,0 +1,10 @@ +""" +Created on July 30, 2020 + +@file AppConnections.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.07.30 +@version 0.1 +@company University of Alberta - Computing Science +""" \ No newline at end of file diff --git a/ConfigReader/AppConnectionsTestCases.py b/ConfigReader/AppConnectionsTestCases.py new file mode 100644 index 0000000..621f1f4 --- /dev/null +++ b/ConfigReader/AppConnectionsTestCases.py @@ -0,0 +1,10 @@ +""" +Created on July 30, 2020 + +@file AppConnectionsTestCases.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.07.30 +@version 0.1 +@company University of Alberta - Computing Science +""" \ No newline at end of file diff --git a/ConfigReader/ConfigErrors.py b/ConfigReader/ConfigErrors.py index 3ae27e1..3dd8f62 100644 --- a/ConfigReader/ConfigErrors.py +++ b/ConfigReader/ConfigErrors.py @@ -1,7 +1,14 @@ """ +Created on July 30, 2020 File was created to store all the errors created for Config reading -""" +@file ConfigErrors.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.07.30 +@version 0.1 +@company University of Alberta - Computing Science +""" class ImmutableObjectError(Exception): """Raised when an Immutable object is being edited""" diff --git a/ConfigReader/ConfigReader.py b/ConfigReader/ConfigReader.py index 67e59d5..738521f 100644 --- a/ConfigReader/ConfigReader.py +++ b/ConfigReader/ConfigReader.py @@ -1,3 +1,15 @@ +""" +Created on July 30, 2020 +File contains the classes that will read the config files. + +@file ConfigReader.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.07.30 +@version 0.1 +@company University of Alberta - Computing Science +""" + import json diff --git a/ConfigReader/NetworkConnection.py b/ConfigReader/NetworkConnection.py index 4059d2b..b315c41 100644 --- a/ConfigReader/NetworkConnection.py +++ b/ConfigReader/NetworkConnection.py @@ -1,3 +1,15 @@ +""" +Created on July 30, 2020 +File contains the class that will store network connections. + +@file NetworkConnection.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.07.30 +@version 0.1 +@company University of Alberta - Computing Science +""" + from ConfigErrors import ImmutableObjectError from ValidationFunctions import check_network_connection_nodes, check_network_connection_type diff --git a/ConfigReader/NetworkConnectionTestCases.py b/ConfigReader/NetworkConnectionTestCases.py index 79af6ce..91c5253 100644 --- a/ConfigReader/NetworkConnectionTestCases.py +++ b/ConfigReader/NetworkConnectionTestCases.py @@ -1,3 +1,15 @@ +""" +Created on July 30, 2020 +Test cases for testing NetworkConnections + +@file NetworkConnectionTestCases.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.07.30 +@version 0.1 +@company University of Alberta - Computing Science +""" + import unittest from ConfigErrors import NetworkConnectionNumberOfNodesNotCorrect, NetworkConnectionHasNodesWithConnectionToSelf, \ InvalidNetworkType @@ -61,5 +73,6 @@ def test_incorrect_network_type(self): with self.assertRaises(InvalidNetworkType): nc = NetworkConnection(["123", "321"], "some") + if __name__ == '__main__': unittest.main() diff --git a/ConfigReader/Node.py b/ConfigReader/Node.py index 922616e..58c121c 100644 --- a/ConfigReader/Node.py +++ b/ConfigReader/Node.py @@ -1,3 +1,15 @@ +""" +Created on July 30, 2020 +File contains the class that will store nodes. + +@file Node.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.07.30 +@version 0.1 +@company University of Alberta - Computing Science +""" + from ConfigErrors import ImmutableObjectError from ValidationFunctions import check_location_coordinates, check_network_card_type_and_access_point_value, \ check_non_empty_non_none_string diff --git a/ConfigReader/NodeTestCases.py b/ConfigReader/NodeTestCases.py index 813e562..ecba530 100644 --- a/ConfigReader/NodeTestCases.py +++ b/ConfigReader/NodeTestCases.py @@ -1,3 +1,14 @@ +""" +Created on July 30, 2020 +File contains the class that will store nodes. + +@file NodeTestCases.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.07.30 +@version 0.1 +@company University of Alberta - Computing Science +""" import unittest from Node import Node diff --git a/ConfigReader/ValidationFunctions.py b/ConfigReader/ValidationFunctions.py index 3edfccc..3daa020 100644 --- a/ConfigReader/ValidationFunctions.py +++ b/ConfigReader/ValidationFunctions.py @@ -1,6 +1,15 @@ """ +Created on July 30, 2020 File contains all the validation tests needed to make sure the values stored in the Classes are valid. + +@file ValidationFunctions.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.07.30 +@version 0.1 +@company University of Alberta - Computing Science """ + from ConfigErrors import InvalidNetworkType, InvalidAccessPointValueForNICType, \ NetworkConnectionNumberOfNodesNotCorrect, NetworkConnectionHasNodesWithConnectionToSelf @@ -61,6 +70,7 @@ def check_network_connection_type(network_connection_type): if len(set(network_connection_type).intersection(set(valid_nic_types))) != len(network_connection_type): raise InvalidNetworkType + def check_network_connection_nodes(nodes): """ Method checks to make sure there are only two nodes passed into the connection. Also checks to make sure that each From 56de50e0608344c4caf2641520de79d8e64e344f Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Wed, 5 Aug 2020 14:46:47 -0600 Subject: [PATCH 14/22] NIC classes and tests created. Node updated - NIC Classes created - Tests for the NIC classes created - Node Updated - Node NIC validation function updated - Node tests updated --- ConfigReader/AllNICTestCases.py | 81 ++++++++++++ ConfigReader/AppConnection.py | 43 ++++++ ...TestCases.py => AppConnectionTestCases.py} | 13 +- ConfigReader/AppConnections.py | 10 -- ConfigReader/ConfigErrors.py | 1 - ConfigReader/NICs.py | 63 +++++++++ ConfigReader/Node.py | 7 +- ConfigReader/NodeTestCases.py | 27 ++-- ConfigReader/ValidationFunctions.py | 35 ++--- TapControl/tapcontrol/data/ieee13.json | 125 ++++++++++++------ 10 files changed, 320 insertions(+), 85 deletions(-) create mode 100644 ConfigReader/AllNICTestCases.py create mode 100644 ConfigReader/AppConnection.py rename ConfigReader/{AppConnectionsTestCases.py => AppConnectionTestCases.py} (52%) delete mode 100644 ConfigReader/AppConnections.py create mode 100644 ConfigReader/NICs.py diff --git a/ConfigReader/AllNICTestCases.py b/ConfigReader/AllNICTestCases.py new file mode 100644 index 0000000..3f7f1f3 --- /dev/null +++ b/ConfigReader/AllNICTestCases.py @@ -0,0 +1,81 @@ +""" +Created on August 5, 2020 +File contains the class that will test NIC class. Super simple in this case. + +@file AllNICTestCases.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.08.05 +@version 0.1 +@company University of Alberta - Computing Science +""" + +import unittest + +from NICs import NIC, P2PNIC, WiFiNIC +from ConfigErrors import ImmutableObjectError + + +class AllNICTestCases(unittest.TestCase): + """ + Tests were created to test the NIC class and its sub-classes + """ + + def test_type_of_nic_base(self): + """ + Tests the type of NIC base class. No error + :return: + """ + nic = NIC() + self.assertEqual("base", nic.type, "TYPE FOR BASE NIC CLASS IS NOT base") + + def test_type_of_nic_p2p(self): + """ + Tests the type of NIC p2p class. No Error + :return: + """ + nic = P2PNIC() + self.assertEqual("p2p", nic.type, "TYPE FOR BASE NIC CLASS IS NOT p2p") + + def test_change_of_type_in_nic_p2p(self): + """ + Tries to change the type of the P2P NIC card. Should throw an error. + :return: + """ + with self.assertRaises(ImmutableObjectError): + nic = P2PNIC() + nic.type = "another_type" + + def test_type_of_nic_wifi(self): + """ + Tests the type of NIC wifi class. No Error + :return: + """ + nic = WiFiNIC() + self.assertEqual("wifi", nic.type, "TYPE FOR BASE NIC CLASS IS NOT wifi") + + def test_change_of_type_in_nic_wifi(self): + """ + Tries to change the type of the P2P NIC card. Should throw an error. + :return: + """ + with self.assertRaises(ImmutableObjectError): + nic = WiFiNIC() + nic.type = "another_type" + + def test_access_point_setting_at_init_in_wifi_nic(self): + """ + Checks that the wifi access point can be set to false/true at the init of WifiNIC + :return: + """ + # Create a NIC without setting access_point + nic = WiFiNIC() + self.assertEqual(False, nic.access_point, "WIFI NIC ACCESS POINT NOW FALSE WHEN NOT SET IN INIT") + nic = WiFiNIC(access_point=False) + self.assertEqual(False, nic.access_point, "WIFI NIC ACCESS POINT NOW FALSE WHEN SET IN INIT") + nic = WiFiNIC(access_point=True) + self.assertEqual(True, nic.access_point, "WIFI NIC ACCESS POINT NOW TRUE WHEN SET IN INIT") + + +if __name__ == '__main__': + unittest.main() diff --git a/ConfigReader/AppConnection.py b/ConfigReader/AppConnection.py new file mode 100644 index 0000000..3c18cae --- /dev/null +++ b/ConfigReader/AppConnection.py @@ -0,0 +1,43 @@ +""" +Created on July 30, 2020 + +@file AppConnection.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.07.30 +@version 0.1 +@company University of Alberta - Computing Science +""" + + +class AppConnection: + """ + Class was created to store the application connections. This does not include physical connections between nodes, + it only includes server/client connections between nodes + """ + # Stores the server + server = "" + # Stores the client + client = "" + # Store the type of the client + client_type = "" + + def __init__(self, nodes, conn_type): + """ + Validates all the information passed in and stores it within itself. Meaning the server and client id should be + of type string and not empty. The client type should be of type sensor or controller. Not other strings or + actuator. + :param nodes: + :param type: + """ + # check_network_connection_nodes(nodes) + # super(NetworkConnection, self).__setattr__('conn_type', conn_type) + + def __setattr__(self, key, value): + """ + Overridden to ensure that nothing in the class is mutable after creation + :param key: + :param value: + :return: + """ + raise ImmutableObjectError diff --git a/ConfigReader/AppConnectionsTestCases.py b/ConfigReader/AppConnectionTestCases.py similarity index 52% rename from ConfigReader/AppConnectionsTestCases.py rename to ConfigReader/AppConnectionTestCases.py index 621f1f4..023e9b5 100644 --- a/ConfigReader/AppConnectionsTestCases.py +++ b/ConfigReader/AppConnectionTestCases.py @@ -7,4 +7,15 @@ @date 2020.07.30 @version 0.1 @company University of Alberta - Computing Science -""" \ No newline at end of file +""" + +import unittest + + +class AppConnectionsTestCases(unittest.TestCase): + def test_something(self): + self.assertEqual(True, False) + + +if __name__ == '__main__': + unittest.main() diff --git a/ConfigReader/AppConnections.py b/ConfigReader/AppConnections.py deleted file mode 100644 index cd85a94..0000000 --- a/ConfigReader/AppConnections.py +++ /dev/null @@ -1,10 +0,0 @@ -""" -Created on July 30, 2020 - -@file AppConnections.py -@author Amrinder S. Grewal -@email asgrewal@ualberta.ca -@date 2020.07.30 -@version 0.1 -@company University of Alberta - Computing Science -""" \ No newline at end of file diff --git a/ConfigReader/ConfigErrors.py b/ConfigReader/ConfigErrors.py index 3dd8f62..421eeee 100644 --- a/ConfigReader/ConfigErrors.py +++ b/ConfigReader/ConfigErrors.py @@ -36,4 +36,3 @@ class NetworkConnectionNumberOfNodesNotCorrect(Exception): class NetworkConnectionHasNodesWithConnectionToSelf(Exception): """Raised when a node is connected to itself in the network connection.""" pass - diff --git a/ConfigReader/NICs.py b/ConfigReader/NICs.py new file mode 100644 index 0000000..f1173f1 --- /dev/null +++ b/ConfigReader/NICs.py @@ -0,0 +1,63 @@ +""" +Created on August 5, 2020 +File contains all NIC type classes. + +@file NICs.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.08.05 +@version 0.1 +@company University of Alberta - Computing Science +""" +from ConfigErrors import ImmutableObjectError + + +class NIC: + """ + Created to store the base type of NIC, where its not specified to be p2p or wifi, etc. + """ + # Stores the type of card, this cannot be set, each class has its own type that is set but cannot be changed + type = "base" + + +class P2PNIC(NIC): + """ + Created to store the p2p NIC card. + """ + # Stores the type of card, this cannot be set, each class has its own type that is set but cannot be changed + type = "p2p" + + def __setattr__(self, key, value): + """ + Overridden to ensure that nothing in the class is mutable after creation + :param key: + :param value: + :return: + """ + raise ImmutableObjectError + + +class WiFiNIC(NIC): + """ + Created to store the Wifi NIC card. + """ + # Stores the type of card, this cannot be set, each class has its own type that is set but cannot be changed + type = "wifi" + # Indicates if the wifi card is an access-point or not, by default its not + access_point = False + + def __init__(self, access_point=False): + """ + Created so that the value of access point can be set on creation of the class + :param access_point: + """ + super(WiFiNIC, self).__setattr__('access_point', access_point) + + def __setattr__(self, key, value): + """ + Overridden to ensure that nothing in the class is mutable after creation + :param key: + :param value: + :return: + """ + raise ImmutableObjectError \ No newline at end of file diff --git a/ConfigReader/Node.py b/ConfigReader/Node.py index 58c121c..170f91e 100644 --- a/ConfigReader/Node.py +++ b/ConfigReader/Node.py @@ -11,8 +11,7 @@ """ from ConfigErrors import ImmutableObjectError -from ValidationFunctions import check_location_coordinates, check_network_card_type_and_access_point_value, \ - check_non_empty_non_none_string +from ValidationFunctions import check_location_coordinates, check_non_empty_non_none_string, check_nic_types class Node: @@ -25,7 +24,7 @@ class Node: network_id = "" # Stores the network of the system location = {} - # Stores the NIC card type + # Stores the NIC card type, should be nic objects that are passed in nic_types = [] # If this network card is a wifi card, then this will be used access_point = False @@ -40,7 +39,7 @@ def __init__(self, power_id, network_id, location, nic_types, access_point=None) self.__check_power_id_type(power_id) self.__check_network_id_type(network_id) check_location_coordinates(location) - check_network_card_type_and_access_point_value(nic_types, access_point) + check_nic_types(nic_types) super(Node, self).__setattr__('power_id', power_id) super(Node, self).__setattr__('network_id', network_id) diff --git a/ConfigReader/NodeTestCases.py b/ConfigReader/NodeTestCases.py index ecba530..0e7d0fd 100644 --- a/ConfigReader/NodeTestCases.py +++ b/ConfigReader/NodeTestCases.py @@ -12,7 +12,8 @@ import unittest from Node import Node -from ConfigErrors import ImmutableObjectError, InvalidNetworkType, InvalidAccessPointValueForNICType +from NICs import P2PNIC, WiFiNIC, NIC +from ConfigErrors import InvalidNetworkType, InvalidAccessPointValueForNICType class NodeTestCases(unittest.TestCase): @@ -116,29 +117,25 @@ def test_none_location_y(self): with self.assertRaises(TypeError): node = Node("test", "test", {"x": "321", "y": None}, ["p2p"]) - def test_invalid_nic_type(self): + def test_incorrect_type_nic(self): """ - Create a node with an invalid type of nic + Create a base type of NIC and a string, should create an error. :return: """ with self.assertRaises(InvalidNetworkType): - node = Node("test", "test", {"x": "321", "y": "123"}, ["not_valid"]) + node = Node("test", "test", {"x": "321", "y": "321"}, [NIC()]) - def test_nic_wifi_with_none_access_point(self): - """ - Create a node with a wifi nic card, but no access point value passed in - :return: - """ - with self.assertRaises(InvalidAccessPointValueForNICType): - node = Node("test", "test", {"x": "321", "y": "123"}, ["wifi"]) + with self.assertRaises(InvalidNetworkType): + node = Node("test", "test", {"x": "321", "y": "321"}, ["p2p"]) - def test_nic_p2p_with_access_point(self): + def test_correct(self): """ - Create a node with a p2p nic card, but with an access point value + Everything is correct, no error should be raised. :return: """ - with self.assertRaises(InvalidAccessPointValueForNICType): - node = Node("test", "test", {"x": "321", "y": "123"}, ["p2p"], access_point=False) + node = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + node = Node("test", "test", {"x": "321", "y": "321"}, [WiFiNIC()]) + node = Node("test", "test", {"x": "321", "y": "321"}, [WiFiNIC(access_point=True)]) if __name__ == '__main__': diff --git a/ConfigReader/ValidationFunctions.py b/ConfigReader/ValidationFunctions.py index 3daa020..deed1c5 100644 --- a/ConfigReader/ValidationFunctions.py +++ b/ConfigReader/ValidationFunctions.py @@ -12,9 +12,11 @@ from ConfigErrors import InvalidNetworkType, InvalidAccessPointValueForNICType, \ NetworkConnectionNumberOfNodesNotCorrect, NetworkConnectionHasNodesWithConnectionToSelf +from NICs import P2PNIC, WiFiNIC # Stores the valid types of nics -valid_nic_types = ["wifi", "p2p"] +valid_nic_types = [P2PNIC, WiFiNIC] + def check_non_empty_non_none_string(to_check): """ @@ -42,23 +44,26 @@ def check_location_coordinates(location_to_check): float(location_to_check['y']) -def check_network_card_type_and_access_point_value(network_card_types, access_point): +def check_nic_types(nics_to_check): """ - Checks the value of network card type, if it is of type wifi or p2p, then check access point value. If type of - NIC is wifi, then access_point should not be None, otherwise it should be None - :param network_card_type: - :param access_point: - :param valid_nic_types: + Check to make sure that all the nics in nics_to_check are of type valid_nic_types and that there are not duplicated. + :param nics_to_check: :return: """ - check_network_connection_type(network_card_types) - - if "wifi" not in network_card_types and access_point is not None: - raise InvalidAccessPointValueForNICType - elif "wifi" in network_card_types: - # Check to make sure access_point is not None and is a bool - if access_point is None or not isinstance(access_point, bool): - raise InvalidAccessPointValueForNICType + types_found = [] + # Iterate through every type and make sure there are no duplicated + for nic in nics_to_check: + found = False + + for valid_nic in valid_nic_types: + if isinstance(nic, valid_nic): + found = True + break + + if not found: + raise InvalidNetworkType + + types_found.append(nic.type) def check_network_connection_type(network_connection_type): diff --git a/TapControl/tapcontrol/data/ieee13.json b/TapControl/tapcontrol/data/ieee13.json index 15927cd..bbfee49 100644 --- a/TapControl/tapcontrol/data/ieee13.json +++ b/TapControl/tapcontrol/data/ieee13.json @@ -8,7 +8,10 @@ "x": "200", "y": "400" }, - "nic_card_types": ["p2p"] + "nic_card_types": [ + { + "type": "p2p" + }] }, { "id": "1", @@ -17,7 +20,10 @@ "x": "200", "y": "350" }, - "nic_card_types": ["p2p"] + "nic_card_types": [ + { + "type": "p2p" + }] }, { "id": "2", @@ -26,7 +32,10 @@ "x": "200", "y": "300" }, - "nic_card_types": ["p2p"] + "nic_card_types": [ + { + "type": "p2p" + }] }, { "id": "3", @@ -35,7 +44,10 @@ "x": "0", "y": "250" }, - "nic_card_types": ["p2p"] + "nic_card_types": [ + { + "type": "p2p" + }] }, { "id": "4", @@ -44,7 +56,10 @@ "x": "100", "y": "250" }, - "nic_card_types": ["p2p"] + "nic_card_types": [ + { + "type": "p2p" + }] }, { "id": "5", @@ -53,8 +68,14 @@ "x": "200", "y": "250" }, - "nic_card_types": ["p2p", "wifi"], - "access_point": true + "nic_card_types": [ + { + "type": "p2p" + }, + { + "type":"wifi", + "access_point": true + }], }, { "id": "6", @@ -63,7 +84,10 @@ "x": "350", "y": "250" }, - "nic_card_types": ["p2p"] + "nic_card_types": [ + { + "type": "p2p" + }] }, { "id": "7", @@ -72,7 +96,10 @@ "x": "400", "y": "250" }, - "nic_card_types": ["p2p"] + "nic_card_types": [ + { + "type": "p2p" + }] }, { "id": "8", @@ -81,7 +108,10 @@ "x": "200", "y": "200" }, - "nic_card_types": ["p2p"] + "nic_card_types": [ + { + "type": "p2p" + }] }, { "id": "9", @@ -90,7 +120,10 @@ "x": "0", "y": "100" }, - "nic_card_types": ["p2p"] + "nic_card_types": [ + { + "type": "p2p" + }] }, { "id": "10", @@ -99,7 +132,10 @@ "x": "100", "y": "100" }, - "nic_card_types": ["p2p"] + "nic_card_types": [ + { + "type": "p2p" + }] }, { "id": "11", @@ -108,7 +144,10 @@ "x": "200", "y": "100" }, - "nic_card_types": ["p2p"] + "nic_card_types": [ + { + "type": "p2p" + }] }, { "id": "12", @@ -117,7 +156,10 @@ "x": "250", "y": "100" }, - "nic_card_types": ["p2p"] + "nic_card_types": [ + { + "type": "p2p" + }] }, { "id": "13", @@ -126,7 +168,10 @@ "x": "400", "y": "100" }, - "nic_card_types": ["p2p"] + "nic_card_types": [ + { + "type": "p2p" + }] }, { "id": "14", @@ -135,7 +180,10 @@ "x": "100", "y": "0" }, - "nic_card_types": ["p2p"] + "nic_card_types": [ + { + "type": "p2p" + }] }, { "id": "15", @@ -144,7 +192,10 @@ "x": "200", "y": "0" }, - "nic_card_types": ["p2p"] + "nic_card_types": [ + { + "type": "p2p" + }] } ], "network_layout": [ @@ -219,8 +270,10 @@ "x": "150", "y": "250" }, - "nic_card_types": ["wifi"], - "access_point": false + "nic_card_types": [{ + "type":"wifi", + "access_point": false + }] }, { "id": "17", @@ -229,8 +282,10 @@ "x": "100", "y": "350" }, - "nic_card_types": ["wifi"], - "access_point": false + "nic_card_types": [{ + "type":"wifi", + "access_point": false + }] }, { "id": "18", @@ -238,8 +293,10 @@ "x": "100", "y": "300" }, - "nic_card_types": ["wifi"], - "access_point": true + "nic_card_types": [{ + "type":"wifi", + "access_point": true + }] } ], "network_layout": [ @@ -259,24 +316,14 @@ }, "app_connections": [ { - "server": "5", - "client": "9", - "client_type": "sensor" - }, - { - "server": "1", - "client": "5", - "client_type": "controller" + "receiver": "5", + "sender": "9", + "path_type": "control" }, { - "server": "5", - "client": "9", - "client_type": "sensor" - }, - { - "server": "5", - "client": "9", - "client_type": "sensor" + "receiver": "1", + "sender": "5", + "path_type": "actuator" } ] } From 1329d2ca5b1737419daaaeb93348a256c00cf1b6 Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Wed, 5 Aug 2020 18:43:05 -0600 Subject: [PATCH 15/22] App Connections and Tests finished - App Connections class finsihed - App Connections class validates the parameters of the init - App Connections test cases finished --- ConfigReader/AppConnectionTestCases.py | 21 ----- ConfigReader/AppConnections.py | 51 ++++++++++++ ConfigReader/AppConnectionsTestCases.py | 97 ++++++++++++++++++++++ ConfigReader/AppConnectionsTypes.py | 42 ++++++++++ ConfigReader/ConfigErrors.py | 10 +++ ConfigReader/NetworkConnection.py | 4 +- ConfigReader/NetworkConnectionTestCases.py | 19 +++-- ConfigReader/NetworkConnectionTypes.py | 42 ++++++++++ ConfigReader/NodeTestCases.py | 25 +++--- ConfigReader/ValidationFunctions.py | 43 +++++++++- 10 files changed, 306 insertions(+), 48 deletions(-) delete mode 100644 ConfigReader/AppConnectionTestCases.py create mode 100644 ConfigReader/AppConnections.py create mode 100644 ConfigReader/AppConnectionsTestCases.py create mode 100644 ConfigReader/AppConnectionsTypes.py create mode 100644 ConfigReader/NetworkConnectionTypes.py diff --git a/ConfigReader/AppConnectionTestCases.py b/ConfigReader/AppConnectionTestCases.py deleted file mode 100644 index 023e9b5..0000000 --- a/ConfigReader/AppConnectionTestCases.py +++ /dev/null @@ -1,21 +0,0 @@ -""" -Created on July 30, 2020 - -@file AppConnectionsTestCases.py -@author Amrinder S. Grewal -@email asgrewal@ualberta.ca -@date 2020.07.30 -@version 0.1 -@company University of Alberta - Computing Science -""" - -import unittest - - -class AppConnectionsTestCases(unittest.TestCase): - def test_something(self): - self.assertEqual(True, False) - - -if __name__ == '__main__': - unittest.main() diff --git a/ConfigReader/AppConnections.py b/ConfigReader/AppConnections.py new file mode 100644 index 0000000..2e4725f --- /dev/null +++ b/ConfigReader/AppConnections.py @@ -0,0 +1,51 @@ +""" +Created on August 05, 2020 +File contains the app connections class, will be used to hold connections between senders and receivers. + +@file AppConnections.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.08.05 +@version 0.1 +@company University of Alberta - Computing Science +""" + +from ValidationFunctions import check_non_empty_non_none_string, check_app_connection_types + + +class AppConnections: + """ + Holds the connection between the server and the receiver and the type of connection + """ + # The node sending the data + sender = "" + # The node receiving the data + receiver = "" + # The type of connection + path_type = None + + def __init__(self, sender, receiver, path_type): + """ + Just validates the sender, the receiver and the path type, then assigns it to the members. + :param sender: + :param receiver: + :param path_type: + """ + # Check that the sender and the receiver ids are valid + check_non_empty_non_none_string(sender) + check_non_empty_non_none_string(receiver) + # Check that the path type is valid + check_app_connection_types(path_type) + + super(AppConnections, self).__setattr__('sender', sender) + super(AppConnections, self).__setattr__('receiver', receiver) + super(AppConnections, self).__setattr__('path_type', path_type) + + def __setattr__(self, key, value): + """ + Overridden to ensure that nothing in the class is mutable after creation + :param key: + :param value: + :return: + """ + raise ImmutableObjectError diff --git a/ConfigReader/AppConnectionsTestCases.py b/ConfigReader/AppConnectionsTestCases.py new file mode 100644 index 0000000..8a835a1 --- /dev/null +++ b/ConfigReader/AppConnectionsTestCases.py @@ -0,0 +1,97 @@ +""" +Created on August 05, 2020 +File contains the types of network connections + +@file AppConnectionsTestCases.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.08.05 +@version 0.1 +@company University of Alberta - Computing Science +""" + +import unittest +from AppConnections import AppConnections +from AppConnectionsTypes import ControlAppConnectionPathType, ActuatorAppConnectionPathType, BaseAppConnectionPathType +from ConfigErrors import InvalidAppConnectionType + + +class AppConnectionsTestCases(unittest.TestCase): + """ + Tests were created to test the AppConnections class + """ + + def test_sender_none(self): + """ + Create a app connection where the sender is none, should throw an error + :return: + """ + with self.assertRaises(TypeError): + app_conn = AppConnections(None, "123", ControlAppConnectionPathType()) + + def test_sender_empty(self): + """ + Create a app connection where the sender is empty, should throw an error + :return: + """ + with self.assertRaises(ValueError): + app_conn = AppConnections("", "123", ControlAppConnectionPathType()) + + def test_sender_type(self): + """ + Create a app connection where the sender is non-string, should throw an error + :return: + """ + with self.assertRaises(TypeError): + app_conn = AppConnections(1, "123", ControlAppConnectionPathType()) + + def test_receiver_none(self): + """ + Create a app connection where the receiver is none, should throw an error + :return: + """ + with self.assertRaises(TypeError): + app_conn = AppConnections("123", None, ControlAppConnectionPathType()) + + def test_receiver_empty(self): + """ + Create a app connection where the receiver is empty, should throw an error + :return: + """ + with self.assertRaises(ValueError): + app_conn = AppConnections("123", "", ControlAppConnectionPathType()) + + def test_receiver_type(self): + """ + Create a app connection where the receiver is non-string, should throw an error + :return: + """ + with self.assertRaises(TypeError): + app_conn = AppConnections("123", 1, ControlAppConnectionPathType()) + + def test_app_connections_base_type(self): + """ + Create a app connection where the path type is base, should throw an error + :return: + """ + with self.assertRaises(InvalidAppConnectionType): + app_conn = AppConnections("123", "123", BaseAppConnectionPathType()) + + + def test_app_connections_actuator_type(self): + """ + Create a app connection where the path type is actuator, no error + :return: + """ + app_conn = AppConnections("123", "123", ActuatorAppConnectionPathType()) + + def test_app_connections_control_type(self): + """ + Create a app connection where the path type is control, no error + :return: + """ + app_conn = AppConnections("123", "123", ControlAppConnectionPathType()) + + +if __name__ == '__main__': + unittest.main() diff --git a/ConfigReader/AppConnectionsTypes.py b/ConfigReader/AppConnectionsTypes.py new file mode 100644 index 0000000..a33f9ec --- /dev/null +++ b/ConfigReader/AppConnectionsTypes.py @@ -0,0 +1,42 @@ +""" +Created on August 05, 2020 +File contains the types of network connections + +@file AppConnectionsTypes.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.08.05 +@version 0.1 +@company University of Alberta - Computing Science +""" + + +class BaseAppConnectionPathType: + """ + The base app connection type. + """ + # Stores the type of the network connection + type = "base" + + def __setattr__(self, key, value): + """ + Overridden to ensure that nothing in the class is mutable after creation + :param key: + :param value: + :return: + """ + raise ImmutableObjectError + + +class ControlAppConnectionPathType(BaseAppConnectionPathType): + """ + A control app connection path type + """ + type = "control" + + +class ActuatorAppConnectionPathType(BaseAppConnectionPathType): + """ + A actuator app connection path type + """ + type = "actuator" diff --git a/ConfigReader/ConfigErrors.py b/ConfigReader/ConfigErrors.py index 421eeee..5f6b715 100644 --- a/ConfigReader/ConfigErrors.py +++ b/ConfigReader/ConfigErrors.py @@ -20,6 +20,16 @@ class InvalidNetworkType(Exception): pass +class InvalidNetworkConnectionType(Exception): + """Raised when an invalid type of network connection is passed in""" + pass + + +class InvalidAppConnectionType(Exception): + """Raised when an invalid type of app connection is passed in""" + pass + + class InvalidAccessPointValueForNICType(Exception): """Raised when: - the value of access point is None or not a bool if NIC is of type wifi diff --git a/ConfigReader/NetworkConnection.py b/ConfigReader/NetworkConnection.py index b315c41..7ace5d0 100644 --- a/ConfigReader/NetworkConnection.py +++ b/ConfigReader/NetworkConnection.py @@ -11,7 +11,7 @@ """ from ConfigErrors import ImmutableObjectError -from ValidationFunctions import check_network_connection_nodes, check_network_connection_type +from ValidationFunctions import check_network_connection_nodes, check_network_connection_types class NetworkConnection: @@ -32,7 +32,7 @@ def __init__(self, nodes, conn_type): :param type: """ check_network_connection_nodes(nodes) - check_network_connection_type([conn_type]) + check_network_connection_types(conn_type) super(NetworkConnection, self).__setattr__('nodes', nodes) super(NetworkConnection, self).__setattr__('conn_type', conn_type) diff --git a/ConfigReader/NetworkConnectionTestCases.py b/ConfigReader/NetworkConnectionTestCases.py index 91c5253..4229a1d 100644 --- a/ConfigReader/NetworkConnectionTestCases.py +++ b/ConfigReader/NetworkConnectionTestCases.py @@ -12,8 +12,9 @@ import unittest from ConfigErrors import NetworkConnectionNumberOfNodesNotCorrect, NetworkConnectionHasNodesWithConnectionToSelf, \ - InvalidNetworkType + InvalidNetworkConnectionType from NetworkConnection import NetworkConnection +from NetworkConnectionTypes import NetworkConnectionP2P, NetworkConnectionTypeBase, NetworkConnectionWiFi class NetworkConnectionTestCases(unittest.TestCase): @@ -26,7 +27,7 @@ def test_too_many_nodes(self): :return: """ with self.assertRaises(NetworkConnectionNumberOfNodesNotCorrect): - nc = NetworkConnection(["123", "321", "5432"], "wifi") + nc = NetworkConnection(["123", "321", "5432"], NetworkConnectionP2P()) def test_too_few_nodes(self): """ @@ -34,7 +35,7 @@ def test_too_few_nodes(self): :return: """ with self.assertRaises(NetworkConnectionNumberOfNodesNotCorrect): - nc = NetworkConnection(["123", "321", "5432"], "wifi") + nc = NetworkConnection(["123", "321", "5432"], NetworkConnectionWiFi()) def test_network_connection_to_self(self): """ @@ -42,36 +43,36 @@ def test_network_connection_to_self(self): :return: """ with self.assertRaises(NetworkConnectionHasNodesWithConnectionToSelf): - nc = NetworkConnection(["123", "123"], "wifi") + nc = NetworkConnection(["123", "123"], NetworkConnectionWiFi()) def test_correct_number_of_nodes(self): """ Creates a NetworkConnection with the correct number of nodes, should not throw an error :return: """ - nc = NetworkConnection(["123", "312"], "wifi") + nc = NetworkConnection(["123", "312"], NetworkConnectionWiFi()) def test_correct_network_type_wifi(self): """ Creates a NetworkConnection with an correct type of network ie, wifi :return: """ - nc = NetworkConnection(["123", "321"], "wifi") + nc = NetworkConnection(["123", "321"], NetworkConnectionWiFi()) def test_correct_network_type_p2p(self): """ Creates a NetworkConnection with an correct type of network ie, p2p :return: """ - nc = NetworkConnection(["123", "321"], "p2p") + nc = NetworkConnection(["123", "321"], NetworkConnectionP2P()) def test_incorrect_network_type(self): """ Creates a NetworkConnection with an incorrect type of network ie, not wifi and not p2p, should throw an error :return: """ - with self.assertRaises(InvalidNetworkType): - nc = NetworkConnection(["123", "321"], "some") + with self.assertRaises(InvalidNetworkConnectionType): + nc = NetworkConnection(["123", "321"], NetworkConnectionTypeBase()) if __name__ == '__main__': diff --git a/ConfigReader/NetworkConnectionTypes.py b/ConfigReader/NetworkConnectionTypes.py new file mode 100644 index 0000000..3dd15b9 --- /dev/null +++ b/ConfigReader/NetworkConnectionTypes.py @@ -0,0 +1,42 @@ +""" +Created on August 05, 2020 +File contains the types of network connections + +@file NetworkConnectionTypes.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.08.05 +@version 0.1 +@company University of Alberta - Computing Science +""" + + +class NetworkConnectionTypeBase: + """ + The base network connection type. + """ + # Stores the type of the network connection + type = "base" + + def __setattr__(self, key, value): + """ + Overridden to ensure that nothing in the class is mutable after creation + :param key: + :param value: + :return: + """ + raise ImmutableObjectError + + +class NetworkConnectionP2P(NetworkConnectionTypeBase): + """ + A p2p network connection type + """ + type = "p2p" + + +class NetworkConnectionWiFi(NetworkConnectionTypeBase): + """ + A WiFi network connection type + """ + type = "wifi" diff --git a/ConfigReader/NodeTestCases.py b/ConfigReader/NodeTestCases.py index 0e7d0fd..3d39594 100644 --- a/ConfigReader/NodeTestCases.py +++ b/ConfigReader/NodeTestCases.py @@ -27,7 +27,7 @@ def test_power_id_none(self): :return: """ with self.assertRaises(TypeError): - node = Node(None, "test", {"x": "123", "y": "321"}, ["p2p"]) + node = Node(None, "test", {"x": "123", "y": "321"}, [P2PNIC()]) def test_power_id_empty(self): """ @@ -35,7 +35,7 @@ def test_power_id_empty(self): :return: """ with self.assertRaises(ValueError): - node = Node("", "test", {"x": "123", "y": "321"}, ["p2p"]) + node = Node("", "test", {"x": "123", "y": "321"}, [P2PNIC()]) def test_power_id_type(self): """ @@ -43,7 +43,7 @@ def test_power_id_type(self): :return: """ with self.assertRaises(TypeError): - node = Node(1, "test", {"x": "123", "y": "321"}, ["p2p"]) + node = Node(1, "test", {"x": "123", "y": "321"}, [P2PNIC()]) def test_network_id_none(self): """ @@ -51,7 +51,7 @@ def test_network_id_none(self): :return: """ with self.assertRaises(TypeError): - node = Node("test", None, {"x": "123", "y": "321"}, ["p2p"]) + node = Node("test", None, {"x": "123", "y": "321"}, [P2PNIC()]) def test_network_id_empty(self): """ @@ -59,7 +59,7 @@ def test_network_id_empty(self): :return: """ with self.assertRaises(ValueError): - node = Node("test", "", {"x": "123", "y": "321"}, ["p2p"]) + node = Node("test", "", {"x": "123", "y": "321"}, [P2PNIC()]) def test_network_id_type(self): """ @@ -67,7 +67,7 @@ def test_network_id_type(self): :return: """ with self.assertRaises(TypeError): - node = Node("test", 1, {"x": "123", "y": "321"}, ["p2p"]) + node = Node("test", 1, {"x": "123", "y": "321"}, [P2PNIC()]) def test_missing_location_x(self): """ @@ -75,7 +75,7 @@ def test_missing_location_x(self): :return: """ with self.assertRaises(KeyError): - node = Node("test", "test", {"y", "123"}, ["p2p"]) + node = Node("test", "test", {"y", "123"}, [P2PNIC()]) def test_missing_location_y(self): """ @@ -83,7 +83,7 @@ def test_missing_location_y(self): :return: """ with self.assertRaises(KeyError): - node = Node("test", "test", {"x": "123"}, ["p2p"]) + node = Node("test", "test", {"x": "123"}, [P2PNIC()]) def test_non_num_location_x(self): """ @@ -91,7 +91,7 @@ def test_non_num_location_x(self): :return: """ with self.assertRaises(ValueError): - node = Node("test", "test", {"x": "a", "y": "123.1"}, ["p2p"]) + node = Node("test", "test", {"x": "a", "y": "123.1"}, [P2PNIC()]) def test_non_num_location_y(self): """ @@ -99,7 +99,7 @@ def test_non_num_location_y(self): :return: """ with self.assertRaises(ValueError): - node = Node("test", "test", {"x": "321", "y": "b"}, ["p2p"]) + node = Node("test", "test", {"x": "321", "y": "b"}, [P2PNIC()]) def test_none_location_x(self): """ @@ -107,7 +107,7 @@ def test_none_location_x(self): :return: """ with self.assertRaises(TypeError): - node = Node("test", "test", {"x": None, "y": "123"}, ["p2p"]) + node = Node("test", "test", {"x": None, "y": "123"}, [P2PNIC()]) def test_none_location_y(self): """ @@ -115,7 +115,7 @@ def test_none_location_y(self): :return: """ with self.assertRaises(TypeError): - node = Node("test", "test", {"x": "321", "y": None}, ["p2p"]) + node = Node("test", "test", {"x": "321", "y": None}, [P2PNIC()]) def test_incorrect_type_nic(self): """ @@ -128,6 +128,7 @@ def test_incorrect_type_nic(self): with self.assertRaises(InvalidNetworkType): node = Node("test", "test", {"x": "321", "y": "321"}, ["p2p"]) + def test_correct(self): """ Everything is correct, no error should be raised. diff --git a/ConfigReader/ValidationFunctions.py b/ConfigReader/ValidationFunctions.py index deed1c5..5c53e5e 100644 --- a/ConfigReader/ValidationFunctions.py +++ b/ConfigReader/ValidationFunctions.py @@ -11,11 +11,16 @@ """ from ConfigErrors import InvalidNetworkType, InvalidAccessPointValueForNICType, \ - NetworkConnectionNumberOfNodesNotCorrect, NetworkConnectionHasNodesWithConnectionToSelf + NetworkConnectionNumberOfNodesNotCorrect, NetworkConnectionHasNodesWithConnectionToSelf, \ + InvalidNetworkConnectionType, InvalidAppConnectionType from NICs import P2PNIC, WiFiNIC +from NetworkConnectionTypes import NetworkConnectionWiFi, NetworkConnectionP2P +from AppConnectionsTypes import ControlAppConnectionPathType, ActuatorAppConnectionPathType # Stores the valid types of nics valid_nic_types = [P2PNIC, WiFiNIC] +valid_network_connection_types = [NetworkConnectionP2P, NetworkConnectionWiFi] +valid_app_connection_types = [ActuatorAppConnectionPathType, ControlAppConnectionPathType] def check_non_empty_non_none_string(to_check): @@ -66,14 +71,44 @@ def check_nic_types(nics_to_check): types_found.append(nic.type) -def check_network_connection_type(network_connection_type): +def check_if_passed_in_is_of_valid_type(passed_in, valid_types): + """ + Iterates through valid_types to check if passed_in is of that type. + :param passed_in: + :param valid_types: + :return: + """ + found = False + for valid_type in valid_types: + if isinstance(passed_in, valid_type): + found = True + break + + return found + + +def check_network_connection_types(network_connection_type): """ Check to see if the network connection type is of a valid type. :param network_connection_type: :return: """ - if len(set(network_connection_type).intersection(set(valid_nic_types))) != len(network_connection_type): - raise InvalidNetworkType + found = check_if_passed_in_is_of_valid_type(network_connection_type, valid_network_connection_types) + + if not found: + raise InvalidNetworkConnectionType + + +def check_app_connection_types(app_connection_type): + """ + Check if the app connection type is of a valid type + :param app_connection_type: + :return: + """ + found = check_if_passed_in_is_of_valid_type(app_connection_type, valid_app_connection_types) + + if not found: + raise InvalidAppConnectionType def check_network_connection_nodes(nodes): From 5add66149716b9d53e1a53a4f5c43994437e3fe2 Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Thu, 6 Aug 2020 17:46:04 -0600 Subject: [PATCH 16/22] Config reader started, nodes read and verified - Config reader started - Nodes are being read - Nodes are checked to make sure there are no duplicate power id or network id - Node and NIC expanded so that == and != work properly and __str__ also overridden - Test cases expanded for NIC and Node to test == and != - Test cases created for Config reader to test Valid Nodes, Duplicate Nodes and a wrong type of NIC --- ConfigReader/Config.py | 125 ++++++++++++++++++ ConfigReader/ConfigErrors.py | 11 ++ ConfigReader/ConfigReader.py | 46 ------- ConfigReader/ConfigTestCases.py | 86 ++++++++++++ .../{AllNICTestCases.py => NICTestCases.py} | 54 +++++++- ConfigReader/NICs.py | 51 ++++++- ConfigReader/Node.py | 65 ++++++++- ConfigReader/NodeTestCases.py | 102 +++++++++++++- .../TestFiles/duplicate_network_id_nodes.json | 47 +++++++ .../TestFiles/duplicate_power_id_nodes.json | 47 +++++++ ConfigReader/TestFiles/valid_nodes.json | 47 +++++++ ConfigReader/TestFiles/wrong_type_nic.json | 47 +++++++ ConfigReader/ValidationFunctions.py | 2 +- TapControl/tapcontrol/data/ieee13.json | 2 +- 14 files changed, 669 insertions(+), 63 deletions(-) create mode 100644 ConfigReader/Config.py delete mode 100644 ConfigReader/ConfigReader.py create mode 100644 ConfigReader/ConfigTestCases.py rename ConfigReader/{AllNICTestCases.py => NICTestCases.py} (59%) create mode 100644 ConfigReader/TestFiles/duplicate_network_id_nodes.json create mode 100644 ConfigReader/TestFiles/duplicate_power_id_nodes.json create mode 100644 ConfigReader/TestFiles/valid_nodes.json create mode 100644 ConfigReader/TestFiles/wrong_type_nic.json diff --git a/ConfigReader/Config.py b/ConfigReader/Config.py new file mode 100644 index 0000000..599a35a --- /dev/null +++ b/ConfigReader/Config.py @@ -0,0 +1,125 @@ +""" +Created on August 30, 2020 +File contains the classes that will read and verify the config files. + +@file Config.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.08.06 +@version 0.1 +@company University of Alberta - Computing Science +""" +import json + +from ConfigErrors import InvalidNetworkType, NodeWithNetworkIdAlreadyExistsInNetwork, \ + NodeWithPowerIdAlreadyExistsInNetwork +from NICs import P2PNIC, WiFiNIC +from Node import Node + + +class Config: + """ + Class was created read, verify and store the verified config file. + """ + # Stores the files passed in + file = None + # Stores all the nodes + nodes = [] + # Store all the ids of the network nodes, used for verification purposes + __network_node_ids = set() + # Store all the ids of the power nodes, used for verification purposes + __power_node_ids = set() + # Stores the Network connection + network_connections = [] + # Stores all the ids of the network connections in a set, used for verification purposes + __network_connections = set() + # Stores the app connections + app_connections = [] + # Stores the app connection ids in a set, used for verification purposes + __app_connections = [] + + def __init__(self, file): + """ + Stores the file pointer passed in. Nothing else is done. + :param file: + """ + # Just save the file pointer + self.file = file + + def __setattr__(self, key, value): + """ + Overridden, once file changes, wipe all the other members + :param key: + :param value: + :return: + """ + # Call super to change the value of the members + super(Config, self).__setattr__(key, value) + # If the changed key was file, then set all the others to their default value + if key == "file": + self.nodes = [] + self.__node_ids = dict() + self.network_connections = [] + self.__network_connections = set() + self.app_connections = [] + self.__app_connections = [] + + def read_config(self): + """ + Reads the config files and the file. + :return: + """ + # Load the config file + data = json.load(self.file) + # Get the primary network out + primary_network = data["primary_network"] + nodes_dict = primary_network["nodes"] + # Load the nodes + self.__read_nodes_from_primary_network(nodes_dict) + + def __read_nodes_from_primary_network(self, data): + """ + Reads the nodes from the primary network, parses them, then verifies them. + - No duplicates + :return: + """ + # Go through every node and create a node from it + for node_dict in data: + node = self.__read_and_create_node(node_dict) + # Check that the node creates no duplicates + if node.network_id in self.__network_node_ids: + raise NodeWithNetworkIdAlreadyExistsInNetwork(node) + if node.power_id in self.__power_node_ids: + raise NodeWithPowerIdAlreadyExistsInNetwork(node) + + # No errors, add to sets and list + self.__network_node_ids.add(node.network_id) + self.__power_node_ids.add(node.power_id) + self.nodes.append(node) + + def __read_and_create_node(self, node_dict): + """ + Reads a dict, creates a node and returns it. + :param node_dict: + :return: + """ + # Just get the values that can be easily fetched + power_id = node_dict["power_network_id"] + network_id = node_dict["id"] + location = node_dict["location"] + + nics = [] + # Convert the NIC strings to NICs + for nic_type in node_dict["nic_card_types"]: + nic = None + if nic_type["type"] == "p2p": + nic = P2PNIC() + elif nic_type["type"] == "wifi": + nic = WiFiNIC(nic_type["access_point"]) + else: + raise InvalidNetworkType + # Add the nic to end + nics.append(nic) + + # Create a node and return it + return Node(power_id, network_id, location, nics) diff --git a/ConfigReader/ConfigErrors.py b/ConfigReader/ConfigErrors.py index 5f6b715..d958a34 100644 --- a/ConfigReader/ConfigErrors.py +++ b/ConfigReader/ConfigErrors.py @@ -10,6 +10,7 @@ @company University of Alberta - Computing Science """ + class ImmutableObjectError(Exception): """Raised when an Immutable object is being edited""" pass @@ -46,3 +47,13 @@ class NetworkConnectionNumberOfNodesNotCorrect(Exception): class NetworkConnectionHasNodesWithConnectionToSelf(Exception): """Raised when a node is connected to itself in the network connection.""" pass + + +class NodeWithNetworkIdAlreadyExistsInNetwork(Exception): + """Raised when a node with a network id is being created that is already taken.""" + pass + + +class NodeWithPowerIdAlreadyExistsInNetwork(Exception): + """Raised when a node with a power id is being created that is already taken.""" + pass diff --git a/ConfigReader/ConfigReader.py b/ConfigReader/ConfigReader.py deleted file mode 100644 index 738521f..0000000 --- a/ConfigReader/ConfigReader.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -Created on July 30, 2020 -File contains the classes that will read the config files. - -@file ConfigReader.py -@author Amrinder S. Grewal -@email asgrewal@ualberta.ca -@date 2020.07.30 -@version 0.1 -@company University of Alberta - Computing Science -""" - -import json - - -class ConfigReader: - """ - Class was created to read the config file passed in. This is done so that the file is only read once and then the - data can be passed to each simulator without having to read the file again. - """ - def __init__(self, file): - """ - The initializer, saves the file pointer passed in. Since the setting of file starts reading the file, this will - also read the file passed in - :param file: - """ - self.file = file - - def __setattr__(self, key, value): - """ - Modified to start reading the file once file has been set - :param key: - :param value: - :return: - """ - # Call the writer like normal - super(ConfigReader, self).__setattr__(key, value) - # Now call the method that will read the file if file was changed - if key == 'file': - self.__read_file() - - def __read_file(self): - """ - Method reads the file pointer that has been stored as the member - :return: - """ diff --git a/ConfigReader/ConfigTestCases.py b/ConfigReader/ConfigTestCases.py new file mode 100644 index 0000000..82a3f19 --- /dev/null +++ b/ConfigReader/ConfigTestCases.py @@ -0,0 +1,86 @@ +""" +Created on August 30, 2020 +File contains tests that will test the reading/verification of config files that are being read by Config + +@file ConfigTestCases.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.08.06 +@version 0.1 +@company University of Alberta - Computing Science +""" +import unittest +from Config import Config +from Node import Node +from NICs import P2PNIC, WiFiNIC +from ConfigErrors import NodeWithNetworkIdAlreadyExistsInNetwork, NodeWithPowerIdAlreadyExistsInNetwork, \ + InvalidNetworkType + + +class ConfigTestCases(unittest.TestCase): + def test_valid_nodes(self): + """ + Passes a file which has valid nodes into Config, no error + :return: + """ + valid_nodes_list = [ + Node("622", "3", {"x": "100", "y": "120"}, [P2PNIC(), WiFiNIC(True)]), + Node("612", "4", {"x": "110", "y": "130"}, [P2PNIC()]), + Node("632", "5", {"x": "120", "y": "140"}, [WiFiNIC()]) + ] + # Read the file + file = open("TestFiles/valid_nodes.json") + config = Config(file) + config.read_config() + # Should have read 3 nodes + self.assertEqual(len(config.nodes), len(valid_nodes_list)) + + # Iterate through the nodes to check their properties + for i in range(0, len(valid_nodes_list)): + self.assertTrue(valid_nodes_list[i] == config.nodes[i]) + + # Everything else should be empty + self.assertEqual(len(config.network_connections), 0) + self.assertEqual(len(config.app_connections), 0) + # Close the file + file.close() + + def test_duplicate_power_id_nodes(self): + """ + Passes a file with duplicate power id nodes into Config, should produce an error + :return: + """ + # Read the file + file = open("TestFiles/duplicate_power_id_nodes.json") + config_dup = Config(file) + with self.assertRaises(NodeWithPowerIdAlreadyExistsInNetwork): + config_dup.read_config() + file.close() + + def test_duplicate_network_id_nodes(self): + """ + Passes a file with duplicate network id nodes into Config, should produce an error + :return: + """ + # Read the file + file = open("TestFiles/duplicate_network_id_nodes.json") + config_dup = Config(file) + with self.assertRaises(NodeWithNetworkIdAlreadyExistsInNetwork): + config_dup.read_config() + file.close() + + def test_nic_wrong_type(self): + """ + Read a file where the NIC type is not valid + :return: + """ + # Read the file + file = open("TestFiles/wrong_type_nic.json") + config_dup = Config(file) + with self.assertRaises(InvalidNetworkType): + config_dup.read_config() + file.close() + + +if __name__ == '__main__': + unittest.main() diff --git a/ConfigReader/AllNICTestCases.py b/ConfigReader/NICTestCases.py similarity index 59% rename from ConfigReader/AllNICTestCases.py rename to ConfigReader/NICTestCases.py index 3f7f1f3..ba384e2 100644 --- a/ConfigReader/AllNICTestCases.py +++ b/ConfigReader/NICTestCases.py @@ -2,7 +2,7 @@ Created on August 5, 2020 File contains the class that will test NIC class. Super simple in this case. -@file AllNICTestCases.py +@file NICTestCases.py @author Amrinder S. Grewal @email asgrewal@ualberta.ca @date 2020.08.05 @@ -27,7 +27,7 @@ def test_type_of_nic_base(self): :return: """ nic = NIC() - self.assertEqual("base", nic.type, "TYPE FOR BASE NIC CLASS IS NOT base") + self.assertEqual("base", nic.nic_type, "TYPE FOR BASE NIC CLASS IS NOT base") def test_type_of_nic_p2p(self): """ @@ -35,7 +35,7 @@ def test_type_of_nic_p2p(self): :return: """ nic = P2PNIC() - self.assertEqual("p2p", nic.type, "TYPE FOR BASE NIC CLASS IS NOT p2p") + self.assertEqual("p2p", nic.nic_type, "TYPE FOR BASE NIC CLASS IS NOT p2p") def test_change_of_type_in_nic_p2p(self): """ @@ -44,7 +44,7 @@ def test_change_of_type_in_nic_p2p(self): """ with self.assertRaises(ImmutableObjectError): nic = P2PNIC() - nic.type = "another_type" + nic.nic_type = "another_type" def test_type_of_nic_wifi(self): """ @@ -52,7 +52,7 @@ def test_type_of_nic_wifi(self): :return: """ nic = WiFiNIC() - self.assertEqual("wifi", nic.type, "TYPE FOR BASE NIC CLASS IS NOT wifi") + self.assertEqual("wifi", nic.nic_type, "TYPE FOR BASE NIC CLASS IS NOT wifi") def test_change_of_type_in_nic_wifi(self): """ @@ -61,7 +61,7 @@ def test_change_of_type_in_nic_wifi(self): """ with self.assertRaises(ImmutableObjectError): nic = WiFiNIC() - nic.type = "another_type" + nic.nic_type = "another_type" def test_access_point_setting_at_init_in_wifi_nic(self): """ @@ -76,6 +76,48 @@ def test_access_point_setting_at_init_in_wifi_nic(self): nic = WiFiNIC(access_point=True) self.assertEqual(True, nic.access_point, "WIFI NIC ACCESS POINT NOW TRUE WHEN SET IN INIT") + def test_eq_for_all_types(self): + """ + Check the equality operator for each type. + :return: + """ + nic1 = WiFiNIC() + nic2 = WiFiNIC() + self.assertTrue(nic1 == nic2) + + nic1 = P2PNIC() + nic2 = P2PNIC() + self.assertTrue(nic1 == nic2) + + nic1 = WiFiNIC(access_point=True) + nic2 = WiFiNIC(access_point=True) + self.assertTrue(nic1 == nic2) + + nic1 = WiFiNIC(access_point=True) + nic2 = WiFiNIC(access_point=False) + self.assertFalse(nic1 == nic2) + + def test_ne_for_all_types(self): + """ + Check if the __ne__ operator is working correctly. + :return: + """ + nic1 = WiFiNIC() + nic2 = WiFiNIC() + self.assertFalse(nic1 != nic2) + + nic1 = P2PNIC() + nic2 = P2PNIC() + self.assertFalse(nic1 != nic2) + + nic1 = WiFiNIC(access_point=True) + nic2 = WiFiNIC(access_point=True) + self.assertFalse(nic1 != nic2) + + nic1 = WiFiNIC(access_point=True) + nic2 = WiFiNIC(access_point=False) + self.assertTrue(nic1 != nic2) + if __name__ == '__main__': unittest.main() diff --git a/ConfigReader/NICs.py b/ConfigReader/NICs.py index f1173f1..a0060df 100644 --- a/ConfigReader/NICs.py +++ b/ConfigReader/NICs.py @@ -17,7 +17,32 @@ class NIC: Created to store the base type of NIC, where its not specified to be p2p or wifi, etc. """ # Stores the type of card, this cannot be set, each class has its own type that is set but cannot be changed - type = "base" + nic_type = "base" + + def __str__(self): + """ + Returns a description of the nic + :return: + """ + return self.nic_type + + def __eq__(self, other): + """ + Method checks to see if the type of other is correct and if type var is equal in self and other. + :param other: + :return: + """ + if isinstance(other, NIC): + return self.nic_type == other.nic_type + return False + + def __ne__(self, other): + """ + Returns the opposite value of __eq__, compares type + :param other: + :return: + """ + return not self.__eq__(other) class P2PNIC(NIC): @@ -25,7 +50,7 @@ class P2PNIC(NIC): Created to store the p2p NIC card. """ # Stores the type of card, this cannot be set, each class has its own type that is set but cannot be changed - type = "p2p" + nic_type = "p2p" def __setattr__(self, key, value): """ @@ -42,7 +67,7 @@ class WiFiNIC(NIC): Created to store the Wifi NIC card. """ # Stores the type of card, this cannot be set, each class has its own type that is set but cannot be changed - type = "wifi" + nic_type = "wifi" # Indicates if the wifi card is an access-point or not, by default its not access_point = False @@ -60,4 +85,22 @@ def __setattr__(self, key, value): :param value: :return: """ - raise ImmutableObjectError \ No newline at end of file + raise ImmutableObjectError + + def __eq__(self, other): + """ + Method checks to see if the type of other is correct and if type var is equal in self and other. + :param other: + :return: + """ + if super(WiFiNIC, self).__eq__(other): + return self.access_point == other.access_point + return False + + def __ne__(self, other): + """ + Returns the opposite value of __eq__, compares type + :param other: + :return: + """ + return not self.__eq__(other) diff --git a/ConfigReader/Node.py b/ConfigReader/Node.py index 170f91e..d7d8951 100644 --- a/ConfigReader/Node.py +++ b/ConfigReader/Node.py @@ -26,10 +26,8 @@ class Node: location = {} # Stores the NIC card type, should be nic objects that are passed in nic_types = [] - # If this network card is a wifi card, then this will be used - access_point = False - def __init__(self, power_id, network_id, location, nic_types, access_point=None): + def __init__(self, power_id, network_id, location, nic_types): """ Validates that all the data necessary is present and is of the correct type and then saves it :param power_id: @@ -45,7 +43,6 @@ def __init__(self, power_id, network_id, location, nic_types, access_point=None) super(Node, self).__setattr__('network_id', network_id) super(Node, self).__setattr__('location', location) super(Node, self).__setattr__('nic_types', nic_types) - super(Node, self).__setattr__('access_point', access_point) def __setattr__(self, key, value): """ @@ -72,3 +69,63 @@ def __check_network_id_type(self, network_id): """ check_non_empty_non_none_string(network_id) + def __eq__(self, other): + """ + Over-ridden to make it easier to compare two nodes and see if they are equal + :param other: + :return: + """ + # Check type of node + if isinstance(other, Node): + return (other.power_id == self.power_id) and \ + (other.network_id == self.network_id) and \ + (other.location["x"] == self.location["x"]) and \ + (other.location["y"] == self.location["y"]) and \ + (self.__compare_nic_types(other.nic_types)) + return False + + def __ne__(self, other): + """ + Over-ridden to make it easier to compare two nodes and see if they are not equal. Just inverts the bool returned + by other. + :param other: + :return: + """ + return not self.__eq__(other) + + def __compare_nic_types(self, other_nics): + """ + Compare's NICs. They need to be in the same order for this to be successful. + :param other_nics: + :return: + """ + # If the length is not the same, return false + if len(self.nic_types) != len(other_nics): + return False + + # If the length if the same, start comparing the NIC types + for i in range(0, len(self.nic_types)): + if self.nic_types[i] != other_nics[i]: + return False + + # Everything matches, return true + return True + + def __str__(self): + """ + Returns a string describing the node. + :return: + """ + string_to_return = "\nNode Object: \n" \ + "\t power_id: " + self.power_id + "\n" \ + "\t network_id: " + self.network_id + "\n" \ + "\t location: " + self.network_id + "\n" \ + "\t nics: " + + for nic in self.nic_types: + string_to_return += ("(" + str(nic) + "), ") + + string_to_return = string_to_return[:-2] + string_to_return += "\n" + + return string_to_return diff --git a/ConfigReader/NodeTestCases.py b/ConfigReader/NodeTestCases.py index 3d39594..f34f97e 100644 --- a/ConfigReader/NodeTestCases.py +++ b/ConfigReader/NodeTestCases.py @@ -117,6 +117,13 @@ def test_none_location_y(self): with self.assertRaises(TypeError): node = Node("test", "test", {"x": "321", "y": None}, [P2PNIC()]) + def test_no_nic(self): + """ + Create a Node with no NIC, should produce no error + :return: + """ + node = Node("test", "test", {"x": "321", "y": "321"}, []) + def test_incorrect_type_nic(self): """ Create a base type of NIC and a string, should create an error. @@ -128,7 +135,6 @@ def test_incorrect_type_nic(self): with self.assertRaises(InvalidNetworkType): node = Node("test", "test", {"x": "321", "y": "321"}, ["p2p"]) - def test_correct(self): """ Everything is correct, no error should be raised. @@ -138,6 +144,100 @@ def test_correct(self): node = Node("test", "test", {"x": "321", "y": "321"}, [WiFiNIC()]) node = Node("test", "test", {"x": "321", "y": "321"}, [WiFiNIC(access_point=True)]) + def test_eq_incorrect_type(self): + """ + Create two identical nodes and check if they are equal. They should not be equal. + :return: + """ + n1 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + n2 = "123" + self.assertFalse(n1 == n2) + + def test_eq_is_equal(self): + """ + Create two identical nodes and check if they are equal. They should be equal. + :return: + """ + n1 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + n2 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + self.assertTrue(n1 == n2) + + def test_eq_not_equal(self): + """ + Create two non-identical nodes and check if they are equal. They should not be equal. + :return: + """ + n1 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + n2 = Node("test1", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + self.assertFalse(n1 == n2) + + n1 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + n2 = Node("test", "test1", {"x": "321", "y": "321"}, [P2PNIC()]) + self.assertFalse(n1 == n2) + + n1 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + n2 = Node("test", "test", {"x": "3211", "y": "321"}, [P2PNIC()]) + self.assertFalse(n1 == n2) + + n1 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + n2 = Node("test", "test", {"x": "321", "y": "3211"}, [P2PNIC()]) + self.assertFalse(n1 == n2) + + n1 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + n2 = Node("test", "test", {"x": "321", "y": "321"}, [WiFiNIC()]) + self.assertFalse(n1 == n2) + + n1 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + n2 = Node("test", "test", {"x": "321", "y": "321"}, [WiFiNIC(), P2PNIC()]) + self.assertFalse(n1 == n2) + + def test_ne_incorrect_type(self): + """ + Create two identical nodes and check if they are equal. Should be true, they are not equal + :return: + """ + n1 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + n2 = "123" + self.assertTrue(n1 != n2) + + def test_ne_is_equal(self): + """ + Create two identical nodes check if they are not equal. Should be false, since they are equal. + :return: + """ + n1 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + n2 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + self.assertFalse(n1 != n2) + + def test_ne_not_equal(self): + """ + Create two non-identical nodes to check if they are not equal. Should be true, since they are not equal. + :return: + """ + n1 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + n2 = Node("test1", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + self.assertTrue(n1 != n2) + + n1 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + n2 = Node("test", "test1", {"x": "321", "y": "321"}, [P2PNIC()]) + self.assertTrue(n1 != n2) + + n1 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + n2 = Node("test", "test", {"x": "3211", "y": "321"}, [P2PNIC()]) + self.assertTrue(n1 != n2) + + n1 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + n2 = Node("test", "test", {"x": "321", "y": "3211"}, [P2PNIC()]) + self.assertTrue(n1 != n2) + + n1 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + n2 = Node("test", "test", {"x": "321", "y": "321"}, [WiFiNIC()]) + self.assertTrue(n1 != n2) + + n1 = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + n2 = Node("test", "test", {"x": "321", "y": "321"}, [WiFiNIC(), P2PNIC()]) + self.assertTrue(n1 != n2) + if __name__ == '__main__': unittest.main() diff --git a/ConfigReader/TestFiles/duplicate_network_id_nodes.json b/ConfigReader/TestFiles/duplicate_network_id_nodes.json new file mode 100644 index 0000000..0b87149 --- /dev/null +++ b/ConfigReader/TestFiles/duplicate_network_id_nodes.json @@ -0,0 +1,47 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "6", + "power_network_id": "623", + "location": { + "x": "100", + "y": "120" + }, + "nic_card_types": [ + { + "type": "p2p" + }, + { + "type": "wifi", + "access_point": true + }] + }, + { + "id": "6", + "power_network_id": "613", + "location": { + "x": "110", + "y": "130" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + }, + { + "id": "7", + "power_network_id": "633", + "location": { + "x": "120", + "y": "140" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": false + }] + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/duplicate_power_id_nodes.json b/ConfigReader/TestFiles/duplicate_power_id_nodes.json new file mode 100644 index 0000000..214ae7f --- /dev/null +++ b/ConfigReader/TestFiles/duplicate_power_id_nodes.json @@ -0,0 +1,47 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "0", + "power_network_id": "621", + "location": { + "x": "100", + "y": "120" + }, + "nic_card_types": [ + { + "type": "p2p" + }, + { + "type": "wifi", + "access_point": true + }] + }, + { + "id": "1", + "power_network_id": "621", + "location": { + "x": "110", + "y": "130" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + }, + { + "id": "2", + "power_network_id": "631", + "location": { + "x": "120", + "y": "140" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": false + }] + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/valid_nodes.json b/ConfigReader/TestFiles/valid_nodes.json new file mode 100644 index 0000000..8a8257c --- /dev/null +++ b/ConfigReader/TestFiles/valid_nodes.json @@ -0,0 +1,47 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "3", + "power_network_id": "622", + "location": { + "x": "100", + "y": "120" + }, + "nic_card_types": [ + { + "type": "p2p" + }, + { + "type": "wifi", + "access_point": true + }] + }, + { + "id": "4", + "power_network_id": "612", + "location": { + "x": "110", + "y": "130" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + }, + { + "id": "5", + "power_network_id": "632", + "location": { + "x": "120", + "y": "140" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": false + }] + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/wrong_type_nic.json b/ConfigReader/TestFiles/wrong_type_nic.json new file mode 100644 index 0000000..e6bd70d --- /dev/null +++ b/ConfigReader/TestFiles/wrong_type_nic.json @@ -0,0 +1,47 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "8", + "power_network_id": "624", + "location": { + "x": "100", + "y": "120" + }, + "nic_card_types": [ + { + "type": "p2p" + }, + { + "type": "wifi", + "access_point": true + }] + }, + { + "id": "9", + "power_network_id": "614", + "location": { + "x": "110", + "y": "130" + }, + "nic_card_types": [ + { + "type": "nil" + }] + }, + { + "id": "10", + "power_network_id": "634", + "location": { + "x": "120", + "y": "140" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": false + }] + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/ValidationFunctions.py b/ConfigReader/ValidationFunctions.py index 5c53e5e..5a7e699 100644 --- a/ConfigReader/ValidationFunctions.py +++ b/ConfigReader/ValidationFunctions.py @@ -68,7 +68,7 @@ def check_nic_types(nics_to_check): if not found: raise InvalidNetworkType - types_found.append(nic.type) + types_found.append(nic.nic_type) def check_if_passed_in_is_of_valid_type(passed_in, valid_types): diff --git a/TapControl/tapcontrol/data/ieee13.json b/TapControl/tapcontrol/data/ieee13.json index bbfee49..1c12df5 100644 --- a/TapControl/tapcontrol/data/ieee13.json +++ b/TapControl/tapcontrol/data/ieee13.json @@ -261,7 +261,7 @@ } ] }, - "secondary_network": { + "secondary_networks": { "nodes": [ { "id": "16", From 87eb6ec75e4d95671cbeb288e677b90008aea5ea Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Wed, 12 Aug 2020 15:18:35 -0600 Subject: [PATCH 17/22] Network Connections finished. - Network Connection reading finished. - Test cases for NetworkConnection and nodes finished/expanded. --- ConfigReader/Config.py | 131 +++++++++++-- ConfigReader/ConfigErrors.py | 25 +++ ConfigReader/ConfigTestCases.py | 172 ++++++++++++++++-- ConfigReader/NICs.py | 7 + ConfigReader/NetworkConnection.py | 26 +++ ConfigReader/NetworkConnectionTestCases.py | 128 +++++++++++++ ConfigReader/NetworkConnectionTypes.py | 24 ++- ConfigReader/Node.py | 54 +++++- ConfigReader/NodeTestCases.py | 45 +++++ .../TestFiles/duplicate_network_id_nodes.json | 3 +- .../TestFiles/duplicate_power_id_nodes.json | 3 +- .../not_valid_network_duplicate_mixed.json | 56 ++++++ .../not_valid_network_duplicate_p2p.json | 48 +++++ .../not_valid_network_duplicate_wifi.json | 50 +++++ .../not_valid_network_missing_nic_p2p.json | 37 ++++ .../not_valid_network_missing_nic_wifi.json | 38 ++++ .../not_valid_network_missing_node.json | 28 +++ ...ot_valid_network_wifi_no_access_point.json | 43 +++++ ...alid_network_wifi_no_non_access_point.json | 43 +++++ .../valid_network_connections_mixed.json | 123 +++++++++++++ .../valid_network_connections_p2p.json | 108 +++++++++++ .../valid_network_connections_wifi.json | 99 ++++++++++ ConfigReader/TestFiles/valid_nodes.json | 3 +- 23 files changed, 1253 insertions(+), 41 deletions(-) create mode 100644 ConfigReader/TestFiles/not_valid_network_duplicate_mixed.json create mode 100644 ConfigReader/TestFiles/not_valid_network_duplicate_p2p.json create mode 100644 ConfigReader/TestFiles/not_valid_network_duplicate_wifi.json create mode 100644 ConfigReader/TestFiles/not_valid_network_missing_nic_p2p.json create mode 100644 ConfigReader/TestFiles/not_valid_network_missing_nic_wifi.json create mode 100644 ConfigReader/TestFiles/not_valid_network_missing_node.json create mode 100644 ConfigReader/TestFiles/not_valid_network_wifi_no_access_point.json create mode 100644 ConfigReader/TestFiles/not_valid_network_wifi_no_non_access_point.json create mode 100644 ConfigReader/TestFiles/valid_network_connections_mixed.json create mode 100644 ConfigReader/TestFiles/valid_network_connections_p2p.json create mode 100644 ConfigReader/TestFiles/valid_network_connections_wifi.json diff --git a/ConfigReader/Config.py b/ConfigReader/Config.py index 599a35a..8757ff6 100644 --- a/ConfigReader/Config.py +++ b/ConfigReader/Config.py @@ -12,7 +12,11 @@ import json from ConfigErrors import InvalidNetworkType, NodeWithNetworkIdAlreadyExistsInNetwork, \ - NodeWithPowerIdAlreadyExistsInNetwork + NodeWithPowerIdAlreadyExistsInNetwork, NodeInNetworkConnectionDoesNotExist, NetworkConnectionAlreadyExists, \ + InvalidNetworkConnectionType, NoAccessPointFoundInNetworkConnection, NoNonAccessPointFoundInNetworkConnection, \ + NodeInNetworkConnectionDoesHaveCorrectNIC +from NetworkConnection import NetworkConnection +from NetworkConnectionTypes import NetworkConnectionP2P, NetworkConnectionWiFi from NICs import P2PNIC, WiFiNIC from Node import Node @@ -32,7 +36,7 @@ class Config: # Stores the Network connection network_connections = [] # Stores all the ids of the network connections in a set, used for verification purposes - __network_connections = set() + __network_connection_ids = set() # Stores the app connections app_connections = [] # Stores the app connection ids in a set, used for verification purposes @@ -72,12 +76,17 @@ def read_config(self): # Load the config file data = json.load(self.file) # Get the primary network out - primary_network = data["primary_network"] - nodes_dict = primary_network["nodes"] + primary_network_dict = data["primary_network"] + # Load the nodes - self.__read_nodes_from_primary_network(nodes_dict) + nodes_dict = primary_network_dict["nodes"] + self.__read_nodes_from_network(nodes_dict) + + # Loads the network connections in the primary network + network_layout_dict = primary_network_dict["network_layout"] + self.__read_network_connections(network_layout_dict) - def __read_nodes_from_primary_network(self, data): + def __read_nodes_from_network(self, data): """ Reads the nodes from the primary network, parses them, then verifies them. - No duplicates @@ -86,13 +95,6 @@ def __read_nodes_from_primary_network(self, data): # Go through every node and create a node from it for node_dict in data: node = self.__read_and_create_node(node_dict) - # Check that the node creates no duplicates - if node.network_id in self.__network_node_ids: - raise NodeWithNetworkIdAlreadyExistsInNetwork(node) - if node.power_id in self.__power_node_ids: - raise NodeWithPowerIdAlreadyExistsInNetwork(node) - - # No errors, add to sets and list self.__network_node_ids.add(node.network_id) self.__power_node_ids.add(node.power_id) self.nodes.append(node) @@ -117,9 +119,106 @@ def __read_and_create_node(self, node_dict): elif nic_type["type"] == "wifi": nic = WiFiNIC(nic_type["access_point"]) else: - raise InvalidNetworkType + raise InvalidNetworkType(nic_type) # Add the nic to end nics.append(nic) - # Create a node and return it - return Node(power_id, network_id, location, nics) + node = Node(power_id, network_id, location, nics) + # Check that the node creates no duplicates + if network_id in self.__network_node_ids: + raise NodeWithNetworkIdAlreadyExistsInNetwork(node) + if power_id in self.__power_node_ids: + raise NodeWithPowerIdAlreadyExistsInNetwork(node) + + return node + + def __read_network_connections(self, network_layout_dict): + """ + Reads the network connections between nodes, parses them and then verifies them. + - No duplicates + - Both nodes exist + - Both nodes have correct type of NIC + :return: + """ + # Go through each connection and create a node from it + for network_conn_dict in network_layout_dict: + network_connection = self.__read_and_create_network_connections(network_conn_dict) + self.network_connections.append(network_connection) + self.__network_connection_ids.add(tuple(sorted([network_connection.nodes[0], network_connection.nodes[1]]))) + + def __read_and_create_network_connections(self, network_conn_dict): + """ + Reads a network connection, the nodes and the type, converts it to a NetworkConnection class, and verifies the + type connection. + :param self: + :param network_conn_dict: + :return: + """ + # Get the nodes + node_one = network_conn_dict["nodes"][0] + node_two = network_conn_dict["nodes"][1] + + # Check the nodes exist + if node_one not in self.__network_node_ids: + raise NodeInNetworkConnectionDoesNotExist(node_one) + if node_two not in self.__network_node_ids: + raise NodeInNetworkConnectionDoesNotExist(node_two) + + node_one_found = self.__get_node_with_network_id(node_one) + node_two_found = self.__get_node_with_network_id(node_two) + + # Now check if the connection already exists + if tuple(sorted([node_one, node_two])) in self.__network_connection_ids: + raise NetworkConnectionAlreadyExists(node_one_found, node_two_found) + + # Now check if the network connection type is valid + if network_conn_dict["type"] == "p2p": + conn_type = NetworkConnectionP2P() + if not node_one_found.has_p2p_card(): + raise NodeInNetworkConnectionDoesHaveCorrectNIC(node_one_found) + + if not node_two_found.has_p2p_card(): + raise NodeInNetworkConnectionDoesHaveCorrectNIC(node_two_found) + # No additional validation required + elif network_conn_dict["type"] == "wifi": + if not node_one_found.has_wifi_card(): + raise NodeInNetworkConnectionDoesHaveCorrectNIC(node_one_found) + + if not node_two_found.has_wifi_card(): + raise NodeInNetworkConnectionDoesHaveCorrectNIC(node_two_found) + + conn_type = NetworkConnectionWiFi() + found_access_point = False + found_non_access_point = False + # In this case, we need to verify that at least one of the wifi nodes is an access point and the other is + # not + + if not node_one_found.is_wifi_access_point() or not node_two_found.is_wifi_access_point(): + found_non_access_point = True + + if node_one_found.is_wifi_access_point() or node_two_found.is_wifi_access_point(): + found_access_point = True + + # Now check if access point and non-access point node in the network connection has been found + if not found_non_access_point: + raise NoNonAccessPointFoundInNetworkConnection(str(node_one_found), str(node_two_found)) + + if not found_access_point: + raise NoAccessPointFoundInNetworkConnection(str(node_one_found), str(node_two_found)) + else: + raise InvalidNetworkConnectionType(network_conn_dict["type"]) + + # Create a conn and return it + return NetworkConnection([node_one, node_two], conn_type) + + def __get_node_with_network_id(self, network_id): + """ + Returns the node with the passed in network id if found, else return None + :param network_id: + :return: + """ + for node in self.nodes: + if node.network_id == network_id: + return node + + return None diff --git a/ConfigReader/ConfigErrors.py b/ConfigReader/ConfigErrors.py index d958a34..11dbd9f 100644 --- a/ConfigReader/ConfigErrors.py +++ b/ConfigReader/ConfigErrors.py @@ -57,3 +57,28 @@ class NodeWithNetworkIdAlreadyExistsInNetwork(Exception): class NodeWithPowerIdAlreadyExistsInNetwork(Exception): """Raised when a node with a power id is being created that is already taken.""" pass + + +class NodeInNetworkConnectionDoesNotExist(Exception): + """Raised when a node in a network connection does not exist in nodes part of the file.""" + pass + + +class NodeInNetworkConnectionDoesHaveCorrectNIC(Exception): + """Raised when a node in a network connection does not have the correct nic.""" + pass + + +class NetworkConnectionAlreadyExists(Exception): + """Raised when a network connection between two nodes already exists.""" + pass + + +class NoAccessPointFoundInNetworkConnection(Exception): + """Raised when two wifi nodes are connected but an access point has not been found.""" + pass + + +class NoNonAccessPointFoundInNetworkConnection(Exception): + """Raised when two wifi nodes are connected but a non-access-point has not been found.""" + pass diff --git a/ConfigReader/ConfigTestCases.py b/ConfigReader/ConfigTestCases.py index 82a3f19..a94917a 100644 --- a/ConfigReader/ConfigTestCases.py +++ b/ConfigReader/ConfigTestCases.py @@ -13,8 +13,11 @@ from Config import Config from Node import Node from NICs import P2PNIC, WiFiNIC +from NetworkConnection import NetworkConnection from ConfigErrors import NodeWithNetworkIdAlreadyExistsInNetwork, NodeWithPowerIdAlreadyExistsInNetwork, \ - InvalidNetworkType + InvalidNetworkType, NetworkConnectionAlreadyExists, NodeInNetworkConnectionDoesHaveCorrectNIC, \ + NoAccessPointFoundInNetworkConnection, NoNonAccessPointFoundInNetworkConnection, NodeInNetworkConnectionDoesNotExist +from NetworkConnectionTypes import NetworkConnectionP2P, NetworkConnectionWiFi class ConfigTestCases(unittest.TestCase): @@ -45,41 +48,174 @@ def test_valid_nodes(self): # Close the file file.close() - def test_duplicate_power_id_nodes(self): + def __open_file_and_wait_to_raise(self, file_to_open, exception_type): """ - Passes a file with duplicate power id nodes into Config, should produce an error + Opens the file passed in, then check if the exception with type is is raised + :return: + """ + file = open(file_to_open) + config = Config(file) + + with self.assertRaises(exception_type): + config.read_config() + + file.close() + + def __compare_valid_network_connections(self, file_to_open, connections_to_check): + """ + Open the file, create the connections, then check against connections_to_check + :param file_to_open: + :param connections_to_check: :return: """ # Read the file - file = open("TestFiles/duplicate_power_id_nodes.json") - config_dup = Config(file) - with self.assertRaises(NodeWithPowerIdAlreadyExistsInNetwork): - config_dup.read_config() + file = open(file_to_open) + config = Config(file) + config.read_config() + # Check the number of connections is correct + self.assertEqual(len(connections_to_check), len(config.network_connections)) + + # Now iterate and check the network connections + for i in range(0, len(connections_to_check)): + self.assertTrue(connections_to_check[i] == config.network_connections[i]) + + # Close the file file.close() + def test_duplicate_power_id_nodes(self): + """ + Passes a file with duplicate power id nodes into Config, should produce an error + :return: + """ + self.__open_file_and_wait_to_raise("TestFiles/duplicate_power_id_nodes.json", + NodeWithPowerIdAlreadyExistsInNetwork) + def test_duplicate_network_id_nodes(self): """ Passes a file with duplicate network id nodes into Config, should produce an error :return: """ - # Read the file - file = open("TestFiles/duplicate_network_id_nodes.json") - config_dup = Config(file) - with self.assertRaises(NodeWithNetworkIdAlreadyExistsInNetwork): - config_dup.read_config() - file.close() + self.__open_file_and_wait_to_raise("TestFiles/duplicate_network_id_nodes.json", + NodeWithNetworkIdAlreadyExistsInNetwork) def test_nic_wrong_type(self): """ Read a file where the NIC type is not valid :return: """ + self.__open_file_and_wait_to_raise("TestFiles/wrong_type_nic.json", + InvalidNetworkType) + + def test_valid_p2p_network_connections(self): + """ + Read a file where the network connections are all p2p and are valid. + :return: + """ + # Network connections that should be created + network_conns = [ + NetworkConnection(["11111", "11112"], NetworkConnectionP2P()), + NetworkConnection(["11112", "11113"], NetworkConnectionP2P()), + NetworkConnection(["11113", "11115"], NetworkConnectionP2P()), + NetworkConnection(["11115", "11114"], NetworkConnectionP2P()), + NetworkConnection(["11114", "11113"], NetworkConnectionP2P()), + ] + + self.__compare_valid_network_connections("TestFiles/valid_network_connections_p2p.json", network_conns) + + def test_valid_wifi_network_connections(self): + """ + Read a file where the network connections are all wifi and are valid. + :return: + """ + network_conns = [ + NetworkConnection(["21", "22"], NetworkConnectionWiFi()), + NetworkConnection(["21", "25"], NetworkConnectionWiFi()), + NetworkConnection(["23", "24"], NetworkConnectionWiFi()) + ] + self.__compare_valid_network_connections("TestFiles/valid_network_connections_wifi.json", network_conns) + + def test_valid_mixed_network_connections(self): + """ + Read a file where the network connections are wifi and p2p mixed and are valid. + :return: + """ + # Network connections that should be created + network_conns = [ + NetworkConnection(["1111", "1112"], NetworkConnectionP2P()), + NetworkConnection(["1112", "1113"], NetworkConnectionP2P()), + NetworkConnection(["1113", "1115"], NetworkConnectionP2P()), + NetworkConnection(["1115", "1114"], NetworkConnectionP2P()), + NetworkConnection(["1114", "1113"], NetworkConnectionP2P()), + NetworkConnection(["1111", "1115"], NetworkConnectionWiFi()), + ] # Read the file - file = open("TestFiles/wrong_type_nic.json") - config_dup = Config(file) - with self.assertRaises(InvalidNetworkType): - config_dup.read_config() - file.close() + self.__compare_valid_network_connections("TestFiles/valid_network_connections_mixed.json", network_conns) + + def test_not_valid_duplicate_p2p(self): + """ + Read a file where the network connections are all p2p, but are not valid because there are duplicates. + :return: + """ + self.__open_file_and_wait_to_raise("TestFiles/not_valid_network_duplicate_p2p.json", + NetworkConnectionAlreadyExists) + + def test_not_valid_duplicate_wifi(self): + """ + Read a file where the network connections are all wifi, but are not valid because there are duplicates. + :return: + """ + self.__open_file_and_wait_to_raise("TestFiles/not_valid_network_duplicate_wifi.json", + NetworkConnectionAlreadyExists) + + def test_not_valid_duplicate_mixed(self): + """ + Read a file where the network connections are wifi and p2p, but are not valid because there are duplicates. + :return: + """ + self.__open_file_and_wait_to_raise("TestFiles/not_valid_network_duplicate_mixed.json", + NetworkConnectionAlreadyExists) + + def test_not_valid_missing_nic_p2p(self): + """ + Read a file where the network connections p2p, but one of the nodes does not have a p2p nic card. + :return: + """ + self.__open_file_and_wait_to_raise("TestFiles/not_valid_network_missing_nic_p2p.json", + NodeInNetworkConnectionDoesHaveCorrectNIC) + + def test_not_valid_missing_nic_wifi(self): + """ + Read a file where the network connections wifi, but one of the nodes does not have a wifi nic card. + :return: + """ + self.__open_file_and_wait_to_raise("TestFiles/not_valid_network_missing_nic_wifi.json", + NodeInNetworkConnectionDoesHaveCorrectNIC) + + def test_not_valid_wifi_no_access_point(self): + """ + Read a file where the network connections wifi, the connections are valid except there are no access points. So, + there should be an error. + :return: + """ + self.__open_file_and_wait_to_raise("TestFiles/not_valid_network_wifi_no_access_point.json", + NoAccessPointFoundInNetworkConnection) + + def test_not_valid_wifi_only_access_point(self): + """ + Read a file where the network connections wifi, the connections are valid except there are only access points. + So, there should be an error. + :return: + """ + self.__open_file_and_wait_to_raise("TestFiles/not_valid_network_wifi_no_non_access_point.json", + NoNonAccessPointFoundInNetworkConnection) + + def test_missing_network_id(self): + """ + Create valid network connections, but the nodes on one of the connections is missing. + :return: + """ + self.__open_file_and_wait_to_raise("TestFiles/not_valid_network_missing_node.json", + NodeInNetworkConnectionDoesNotExist) if __name__ == '__main__': diff --git a/ConfigReader/NICs.py b/ConfigReader/NICs.py index a0060df..17dba34 100644 --- a/ConfigReader/NICs.py +++ b/ConfigReader/NICs.py @@ -87,6 +87,13 @@ def __setattr__(self, key, value): """ raise ImmutableObjectError + def __str__(self): + """ + Returns a description of the nic + :return: + """ + return self.nic_type + ", access_point: " + str(self.access_point) + def __eq__(self, other): """ Method checks to see if the type of other is correct and if type var is equal in self and other. diff --git a/ConfigReader/NetworkConnection.py b/ConfigReader/NetworkConnection.py index 7ace5d0..866c885 100644 --- a/ConfigReader/NetworkConnection.py +++ b/ConfigReader/NetworkConnection.py @@ -45,3 +45,29 @@ def __setattr__(self, key, value): :return: """ raise ImmutableObjectError + + def __eq__(self, other): + """ + Make sure the nodes are equal and the conn type is equal, return true + :param other: + :return: + """ + if isinstance(other, NetworkConnection): + # Sort the nodes in both + sorted_nodes = sorted(self.nodes) + sorted_nodes_other = sorted(other.nodes) + # Make sure the nodes are equal, and the type is equal + return ( + sorted_nodes[0] == sorted_nodes_other[0] and + sorted_nodes[1] == sorted_nodes_other[1] and + self.conn_type == other.conn_type + ) + return False + + def __ne__(self, other): + """ + Return the opposite of eq. If nodes are not equal or the conn type is not equal, return true + :param other: + :return: + """ + return not self.__eq__(other) diff --git a/ConfigReader/NetworkConnectionTestCases.py b/ConfigReader/NetworkConnectionTestCases.py index 4229a1d..c5e1b58 100644 --- a/ConfigReader/NetworkConnectionTestCases.py +++ b/ConfigReader/NetworkConnectionTestCases.py @@ -74,6 +74,134 @@ def test_incorrect_network_type(self): with self.assertRaises(InvalidNetworkConnectionType): nc = NetworkConnection(["123", "321"], NetworkConnectionTypeBase()) + def test_eq_is_equal_network_connection(self): + """ + Test network connections that are equal with the == operator. + :return: + """ + nc1 = NetworkConnection(["1", "2"], NetworkConnectionP2P()) + nc2 = NetworkConnection(["1", "2"], NetworkConnectionP2P()) + self.assertTrue(nc1 == nc2) + + nc1 = NetworkConnection(["1", "2"], NetworkConnectionWiFi()) + nc2 = NetworkConnection(["1", "2"], NetworkConnectionWiFi()) + self.assertTrue(nc1 == nc2) + + def test_eq_not_equal_network_connection(self): + """ + Test network connections that are not equal with the == operator. + :return: + """ + nc1 = NetworkConnection(["1", "2"], NetworkConnectionP2P()) + nc2 = NetworkConnection(["3", "2"], NetworkConnectionP2P()) + self.assertFalse(nc1 == nc2) + + nc1 = NetworkConnection(["1", "2"], NetworkConnectionP2P()) + nc2 = NetworkConnection(["1", "3"], NetworkConnectionP2P()) + self.assertFalse(nc1 == nc2) + + nc1 = NetworkConnection(["1", "2"], NetworkConnectionWiFi()) + nc2 = NetworkConnection(["3", "2"], NetworkConnectionWiFi()) + self.assertFalse(nc1 == nc2) + + nc1 = NetworkConnection(["1", "2"], NetworkConnectionWiFi()) + nc2 = NetworkConnection(["1", "3"], NetworkConnectionWiFi()) + self.assertFalse(nc1 == nc2) + + nc1 = NetworkConnection(["1", "2"], NetworkConnectionWiFi()) + nc2 = NetworkConnection(["1", "2"], NetworkConnectionP2P()) + self.assertFalse(nc1 == nc2) + + def test_ne_is_equal_network_connection(self): + """ + Test network connections that are equal with the != operator. + :return: + """ + nc1 = NetworkConnection(["1", "2"], NetworkConnectionP2P()) + nc2 = NetworkConnection(["1", "2"], NetworkConnectionP2P()) + self.assertFalse(nc1 != nc2) + + nc1 = NetworkConnection(["1", "2"], NetworkConnectionWiFi()) + nc2 = NetworkConnection(["1", "2"], NetworkConnectionWiFi()) + self.assertFalse(nc1 != nc2) + + def test_ne_not_equal_network_connection(self): + """ + Test network connections that are not equal with the != operator. + :return: + """ + nc1 = NetworkConnection(["1", "2"], NetworkConnectionP2P()) + nc2 = NetworkConnection(["3", "2"], NetworkConnectionP2P()) + self.assertTrue(nc1 != nc2) + + nc1 = NetworkConnection(["1", "2"], NetworkConnectionP2P()) + nc2 = NetworkConnection(["1", "3"], NetworkConnectionP2P()) + self.assertTrue(nc1 != nc2) + + nc1 = NetworkConnection(["1", "2"], NetworkConnectionWiFi()) + nc2 = NetworkConnection(["3", "2"], NetworkConnectionWiFi()) + self.assertTrue(nc1 != nc2) + + nc1 = NetworkConnection(["1", "2"], NetworkConnectionWiFi()) + nc2 = NetworkConnection(["1", "3"], NetworkConnectionWiFi()) + self.assertTrue(nc1 != nc2) + + nc1 = NetworkConnection(["1", "2"], NetworkConnectionWiFi()) + nc2 = NetworkConnection(["1", "2"], NetworkConnectionP2P()) + self.assertTrue(nc1 != nc2) + + def test_eq_is_equal_network_connection_type(self): + """ + Check the connection type with == when they are both equal + :return: + """ + nct1 = NetworkConnectionWiFi() + nct2 = NetworkConnectionWiFi() + self.assertTrue(nct1 == nct2) + + nct1 = NetworkConnectionP2P() + nct2 = NetworkConnectionP2P() + self.assertTrue(nct1 == nct2) + + def test_eq_not_equal_network_connection_type(self): + """ + Check the connection type with == when they are not equal + :return: + """ + nct1 = NetworkConnectionWiFi() + nct2 = NetworkConnectionP2P() + self.assertFalse(nct1 == nct2) + + nct1 = NetworkConnectionP2P() + nct2 = NetworkConnectionWiFi() + self.assertFalse(nct1 == nct2) + + def test_ne_is_equal_network_connection_type(self): + """ + Check the connection type with != when they are both equal + :return: + """ + nct1 = NetworkConnectionWiFi() + nct2 = NetworkConnectionWiFi() + self.assertFalse(nct1 != nct2) + + nct1 = NetworkConnectionP2P() + nct2 = NetworkConnectionP2P() + self.assertFalse(nct1 != nct2) + + def test_ne_not_equal_network_connection_type(self): + """ + Check the connection type with != when they are not equal + :return: + """ + nct1 = NetworkConnectionWiFi() + nct2 = NetworkConnectionP2P() + self.assertTrue(nct1 != nct2) + + nct1 = NetworkConnectionP2P() + nct2 = NetworkConnectionWiFi() + self.assertTrue(nct1 != nct2) + if __name__ == '__main__': unittest.main() diff --git a/ConfigReader/NetworkConnectionTypes.py b/ConfigReader/NetworkConnectionTypes.py index 3dd15b9..901962d 100644 --- a/ConfigReader/NetworkConnectionTypes.py +++ b/ConfigReader/NetworkConnectionTypes.py @@ -16,7 +16,7 @@ class NetworkConnectionTypeBase: The base network connection type. """ # Stores the type of the network connection - type = "base" + conn_type = "base" def __setattr__(self, key, value): """ @@ -27,16 +27,34 @@ def __setattr__(self, key, value): """ raise ImmutableObjectError + def __eq__(self, other): + """ + Checks to see if conn_type of two NetworkConnections is the same + :param other: + :return: + """ + if isinstance(other, NetworkConnectionTypeBase): + return self.conn_type == other.conn_type + return False + + def __ne__(self, other): + """ + Checks to see if conn_type of two NetworkConnections is not the same, opposite of eq + :param other: + :return: + """ + return not self.__eq__(other) + class NetworkConnectionP2P(NetworkConnectionTypeBase): """ A p2p network connection type """ - type = "p2p" + conn_type = "p2p" class NetworkConnectionWiFi(NetworkConnectionTypeBase): """ A WiFi network connection type """ - type = "wifi" + conn_type = "wifi" diff --git a/ConfigReader/Node.py b/ConfigReader/Node.py index d7d8951..41a4d46 100644 --- a/ConfigReader/Node.py +++ b/ConfigReader/Node.py @@ -12,7 +12,7 @@ from ConfigErrors import ImmutableObjectError from ValidationFunctions import check_location_coordinates, check_non_empty_non_none_string, check_nic_types - +from NICs import P2PNIC, WiFiNIC class Node: """ @@ -44,6 +44,34 @@ def __init__(self, power_id, network_id, location, nic_types): super(Node, self).__setattr__('location', location) super(Node, self).__setattr__('nic_types', nic_types) + def has_p2p_card(self): + """ + Check the nics to see if it has a p2p card. + :return: + """ + return self.__has_type_of_card(P2PNIC) + + def has_wifi_card(self): + """ + Check the nics to see if it has a wifi card. + :return: + """ + return self.__has_type_of_card(WiFiNIC) + + def is_wifi_access_point(self): + """ + Check the nics to see if it has a wifi card. + :return: + """ + # Get wifi cards + wifi_cards = self.__get_type_of_cards(WiFiNIC) + if len(wifi_cards) > 0: + for card in wifi_cards: + if card.access_point: + return True + + return False + def __setattr__(self, key, value): """ Overridden to ensure that nothing in the class is mutable after creation @@ -53,6 +81,30 @@ def __setattr__(self, key, value): """ raise ImmutableObjectError + def __has_type_of_card(self, type): + """ + Check to see if Node has a type of card in nic_types + :param type: + :return: + """ + if len(self.__get_type_of_cards(type)) > 0: + return True + else: + return False + + def __get_type_of_cards(self, type): + """ + Gets and returns all the cards of type, well type + :param type: + :return: + """ + to_return = [] + for card in self.nic_types: + if isinstance(card, type): + to_return.append(card) + + return to_return + def __check_power_id_type(self, power_id): """ Checks that the power id passed in is a non-empty string. diff --git a/ConfigReader/NodeTestCases.py b/ConfigReader/NodeTestCases.py index f34f97e..d5f34fa 100644 --- a/ConfigReader/NodeTestCases.py +++ b/ConfigReader/NodeTestCases.py @@ -238,6 +238,51 @@ def test_ne_not_equal(self): n2 = Node("test", "test", {"x": "321", "y": "321"}, [WiFiNIC(), P2PNIC()]) self.assertTrue(n1 != n2) + def test_has_p2p_card(self): + """ + Check to see if has_p2p_card method is working properly + :return: + """ + n = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + self.assertTrue(n.has_p2p_card()) + + n = Node("test", "test", {"x": "321", "y": "321"}, [WiFiNIC()]) + self.assertFalse(n.has_p2p_card()) + + n = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC(), WiFiNIC()]) + self.assertTrue(n.has_p2p_card()) + + def test_has_wifi_card(self): + """ + Check to see if has_wifi_card method is working properly + :return: + """ + n = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + self.assertFalse(n.has_wifi_card()) + + n = Node("test", "test", {"x": "321", "y": "321"}, [WiFiNIC()]) + self.assertTrue(n.has_wifi_card()) + + n = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC(), WiFiNIC()]) + self.assertTrue(n.has_wifi_card()) + + def test_is_wifi_access_point(self): + """ + Check to see if is_wifi_access_point method is working properly + :return: + """ + n = Node("test", "test", {"x": "321", "y": "321"}, [P2PNIC()]) + self.assertFalse(n.is_wifi_access_point()) + + n = Node("test", "test", {"x": "321", "y": "321"}, [WiFiNIC()]) + self.assertFalse(n.is_wifi_access_point()) + + n = Node("test", "test", {"x": "321", "y": "321"}, [WiFiNIC(access_point=False)]) + self.assertFalse(n.is_wifi_access_point()) + + n = Node("test", "test", {"x": "321", "y": "321"}, [WiFiNIC(access_point=True)]) + self.assertTrue(n.is_wifi_access_point()) + if __name__ == '__main__': unittest.main() diff --git a/ConfigReader/TestFiles/duplicate_network_id_nodes.json b/ConfigReader/TestFiles/duplicate_network_id_nodes.json index 0b87149..bfff743 100644 --- a/ConfigReader/TestFiles/duplicate_network_id_nodes.json +++ b/ConfigReader/TestFiles/duplicate_network_id_nodes.json @@ -42,6 +42,7 @@ "access_point": false }] } - ] + ], + "network_layout": [] } } \ No newline at end of file diff --git a/ConfigReader/TestFiles/duplicate_power_id_nodes.json b/ConfigReader/TestFiles/duplicate_power_id_nodes.json index 214ae7f..2dbb58c 100644 --- a/ConfigReader/TestFiles/duplicate_power_id_nodes.json +++ b/ConfigReader/TestFiles/duplicate_power_id_nodes.json @@ -42,6 +42,7 @@ "access_point": false }] } - ] + ], + "network_layout": [] } } \ No newline at end of file diff --git a/ConfigReader/TestFiles/not_valid_network_duplicate_mixed.json b/ConfigReader/TestFiles/not_valid_network_duplicate_mixed.json new file mode 100644 index 0000000..d87e001 --- /dev/null +++ b/ConfigReader/TestFiles/not_valid_network_duplicate_mixed.json @@ -0,0 +1,56 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "111145", + "power_network_id": "1111145", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": true + }, + { + "type": "p2p" + } + ] + }, + { + "id": "111146", + "power_network_id": "1111146", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": false + }, + { + "type": "p2p" + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "111145", + "111146" + ], + "type": "p2p" + }, + { + "nodes": [ + "111146", + "111145" + ], + "type": "wifi" + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/not_valid_network_duplicate_p2p.json b/ConfigReader/TestFiles/not_valid_network_duplicate_p2p.json new file mode 100644 index 0000000..463932d --- /dev/null +++ b/ConfigReader/TestFiles/not_valid_network_duplicate_p2p.json @@ -0,0 +1,48 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "43", + "power_network_id": "100", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + }, + { + "id": "44", + "power_network_id": "101", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "43", + "44" + ], + "type": "p2p" + }, + { + "nodes": [ + "43", + "44" + ], + "type": "p2p" + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/not_valid_network_duplicate_wifi.json b/ConfigReader/TestFiles/not_valid_network_duplicate_wifi.json new file mode 100644 index 0000000..b118e7b --- /dev/null +++ b/ConfigReader/TestFiles/not_valid_network_duplicate_wifi.json @@ -0,0 +1,50 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "45", + "power_network_id": "145", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": true + } + ] + }, + { + "id": "46", + "power_network_id": "146", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": false + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "45", + "46" + ], + "type": "wifi" + }, + { + "nodes": [ + "46", + "45" + ], + "type": "wifi" + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/not_valid_network_missing_nic_p2p.json b/ConfigReader/TestFiles/not_valid_network_missing_nic_p2p.json new file mode 100644 index 0000000..c76b49c --- /dev/null +++ b/ConfigReader/TestFiles/not_valid_network_missing_nic_p2p.json @@ -0,0 +1,37 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "43123213", + "power_network_id": "10123421340", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [] + }, + { + "id": "44123123", + "power_network_id": "10123412341", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "43123213", + "44123123" + ], + "type": "p2p" + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/not_valid_network_missing_nic_wifi.json b/ConfigReader/TestFiles/not_valid_network_missing_nic_wifi.json new file mode 100644 index 0000000..ae903b3 --- /dev/null +++ b/ConfigReader/TestFiles/not_valid_network_missing_nic_wifi.json @@ -0,0 +1,38 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "434321321", + "power_network_id": "10sdafada0", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [] + }, + { + "id": "444321321423", + "power_network_id": "1dasfsasd01", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": true + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "434321321", + "444321321423" + ], + "type": "wifi" + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/not_valid_network_missing_node.json b/ConfigReader/TestFiles/not_valid_network_missing_node.json new file mode 100644 index 0000000..10b4aca --- /dev/null +++ b/ConfigReader/TestFiles/not_valid_network_missing_node.json @@ -0,0 +1,28 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "430000", + "power_network_id": "10000000", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "430000", + "440000" + ], + "type": "p2p" + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/not_valid_network_wifi_no_access_point.json b/ConfigReader/TestFiles/not_valid_network_wifi_no_access_point.json new file mode 100644 index 0000000..003c324 --- /dev/null +++ b/ConfigReader/TestFiles/not_valid_network_wifi_no_access_point.json @@ -0,0 +1,43 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "21111", + "power_network_id": "110000", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": false + } + ] + }, + { + "id": "22111", + "power_network_id": "111000", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": false + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "21111", + "22111" + ], + "type": "wifi" + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/not_valid_network_wifi_no_non_access_point.json b/ConfigReader/TestFiles/not_valid_network_wifi_no_non_access_point.json new file mode 100644 index 0000000..290fb32 --- /dev/null +++ b/ConfigReader/TestFiles/not_valid_network_wifi_no_non_access_point.json @@ -0,0 +1,43 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "211143211", + "power_network_id": "110431234000", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": true + } + ] + }, + { + "id": "221143214511", + "power_network_id": "1110034211310", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": true + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "211143211", + "221143214511" + ], + "type": "wifi" + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/valid_network_connections_mixed.json b/ConfigReader/TestFiles/valid_network_connections_mixed.json new file mode 100644 index 0000000..582d281 --- /dev/null +++ b/ConfigReader/TestFiles/valid_network_connections_mixed.json @@ -0,0 +1,123 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "1111", + "power_network_id": "11100", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "p2p" + }, + { + "type": "wifi", + "access_point": true + } + ] + }, + { + "id": "1112", + "power_network_id": "11101", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + }, + { + "id": "1113", + "power_network_id": "11102", + "location": { + "x": "200", + "y": "300" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + }, + { + "id": "1114", + "power_network_id": "11103", + "location": { + "x": "0", + "y": "250" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + }, + { + "id": "1115", + "power_network_id": "11104", + "location": { + "x": "100", + "y": "250" + }, + "nic_card_types": [ + { + "type": "p2p" + }, + { + "type": "wifi", + "access_point": false + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "1111", + "1112" + ], + "type": "p2p" + }, + { + "nodes": [ + "1112", + "1113" + ], + "type": "p2p" + }, + { + "nodes": [ + "1113", + "1115" + ], + "type": "p2p" + }, + { + "nodes": [ + "1115", + "1114" + ], + "type": "p2p" + }, + { + "nodes": [ + "1114", + "1113" + ], + "type": "p2p" + }, + { + "nodes": [ + "1111", + "1115" + ], + "type": "wifi" + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/valid_network_connections_p2p.json b/ConfigReader/TestFiles/valid_network_connections_p2p.json new file mode 100644 index 0000000..7d19e94 --- /dev/null +++ b/ConfigReader/TestFiles/valid_network_connections_p2p.json @@ -0,0 +1,108 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "11111", + "power_network_id": "111100", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + }, + { + "id": "11112", + "power_network_id": "111101", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + }, + { + "id": "11113", + "power_network_id": "111102", + "location": { + "x": "200", + "y": "300" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + }, + { + "id": "11114", + "power_network_id": "111103", + "location": { + "x": "0", + "y": "250" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + }, + { + "id": "11115", + "power_network_id": "111104", + "location": { + "x": "100", + "y": "250" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "11111", + "11112" + ], + "type": "p2p" + }, + { + "nodes": [ + "11112", + "11113" + ], + "type": "p2p" + }, + { + "nodes": [ + "11113", + "11115" + ], + "type": "p2p" + }, + { + "nodes": [ + "11115", + "11114" + ], + "type": "p2p" + }, + { + "nodes": [ + "11114", + "11113" + ], + "type": "p2p" + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/valid_network_connections_wifi.json b/ConfigReader/TestFiles/valid_network_connections_wifi.json new file mode 100644 index 0000000..a136709 --- /dev/null +++ b/ConfigReader/TestFiles/valid_network_connections_wifi.json @@ -0,0 +1,99 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "21", + "power_network_id": "110", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": true + } + ] + }, + { + "id": "22", + "power_network_id": "111", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": false + } + ] + }, + { + "id": "23", + "power_network_id": "112", + "location": { + "x": "200", + "y": "300" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": true + } + ] + }, + { + "id": "24", + "power_network_id": "113", + "location": { + "x": "0", + "y": "250" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": false + } + ] + }, + { + "id": "25", + "power_network_id": "114", + "location": { + "x": "110", + "y": "250" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": false + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "21", + "22" + ], + "type": "wifi" + }, + { + "nodes": [ + "21", + "25" + ], + "type": "wifi" + }, + { + "nodes": [ + "24", + "23" + ], + "type": "wifi" + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/valid_nodes.json b/ConfigReader/TestFiles/valid_nodes.json index 8a8257c..9535ae3 100644 --- a/ConfigReader/TestFiles/valid_nodes.json +++ b/ConfigReader/TestFiles/valid_nodes.json @@ -42,6 +42,7 @@ "access_point": false }] } - ] + ], + "network_layout": [] } } \ No newline at end of file From cddeb7707521bca58e70980fb2ab75e6f206466a Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Wed, 12 Aug 2020 17:20:53 -0600 Subject: [PATCH 18/22] App Connections Finished - Config reads app connections - Verifies that nodes in the app connections exist and that the path type is valid - Tests for Config App Connections finished - Added ==, != operator to AppConnections and AppConnectionTypes. - Added test for == and != for AppConnections --- ConfigReader/AppConnection.py | 43 --------- ConfigReader/AppConnections.py | 20 ++++ ConfigReader/AppConnectionsTestCases.py | 89 +++++++++++++++++- ConfigReader/AppConnectionsTypes.py | 24 ++++- ConfigReader/Config.py | 56 ++++++++++- ConfigReader/ConfigErrors.py | 5 + ConfigReader/ConfigTestCases.py | 54 ++++++++++- ConfigReader/Node.py | 12 +-- ConfigReader/NodeTestCases.py | 1 - .../not_valid_app_conn_node_one_missing.json | 52 ++++++++++ .../not_valid_app_conn_node_two_missing.json | 52 ++++++++++ ...ot_valid_app_conn_wrong_path_type_one.json | 52 ++++++++++ ...ot_valid_app_conn_wrong_path_type_two.json | 52 ++++++++++ ConfigReader/TestFiles/valid_app_conns.json | 94 +++++++++++++++++++ .../valid_network_connections_mixed.json | 3 +- .../valid_network_connections_p2p.json | 3 +- .../valid_network_connections_wifi.json | 3 +- ConfigReader/TestFiles/valid_nodes.json | 3 +- 18 files changed, 555 insertions(+), 63 deletions(-) delete mode 100644 ConfigReader/AppConnection.py create mode 100644 ConfigReader/TestFiles/not_valid_app_conn_node_one_missing.json create mode 100644 ConfigReader/TestFiles/not_valid_app_conn_node_two_missing.json create mode 100644 ConfigReader/TestFiles/not_valid_app_conn_wrong_path_type_one.json create mode 100644 ConfigReader/TestFiles/not_valid_app_conn_wrong_path_type_two.json create mode 100644 ConfigReader/TestFiles/valid_app_conns.json diff --git a/ConfigReader/AppConnection.py b/ConfigReader/AppConnection.py deleted file mode 100644 index 3c18cae..0000000 --- a/ConfigReader/AppConnection.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -Created on July 30, 2020 - -@file AppConnection.py -@author Amrinder S. Grewal -@email asgrewal@ualberta.ca -@date 2020.07.30 -@version 0.1 -@company University of Alberta - Computing Science -""" - - -class AppConnection: - """ - Class was created to store the application connections. This does not include physical connections between nodes, - it only includes server/client connections between nodes - """ - # Stores the server - server = "" - # Stores the client - client = "" - # Store the type of the client - client_type = "" - - def __init__(self, nodes, conn_type): - """ - Validates all the information passed in and stores it within itself. Meaning the server and client id should be - of type string and not empty. The client type should be of type sensor or controller. Not other strings or - actuator. - :param nodes: - :param type: - """ - # check_network_connection_nodes(nodes) - # super(NetworkConnection, self).__setattr__('conn_type', conn_type) - - def __setattr__(self, key, value): - """ - Overridden to ensure that nothing in the class is mutable after creation - :param key: - :param value: - :return: - """ - raise ImmutableObjectError diff --git a/ConfigReader/AppConnections.py b/ConfigReader/AppConnections.py index 2e4725f..976943e 100644 --- a/ConfigReader/AppConnections.py +++ b/ConfigReader/AppConnections.py @@ -49,3 +49,23 @@ def __setattr__(self, key, value): :return: """ raise ImmutableObjectError + + def __eq__(self, other): + """ + Compare and make sure the the app connections are equal by comparing sender, receiver and path_type + :param other: + :return: + """ + if isinstance(other, AppConnections): + return (self.sender == other.sender + and self.receiver == other.receiver + and self.path_type == other.path_type) + return False + + def __ne__(self, other): + """ + Returns the opposite of eq. + :param other: + :return: + """ + return not self.__eq__(other) \ No newline at end of file diff --git a/ConfigReader/AppConnectionsTestCases.py b/ConfigReader/AppConnectionsTestCases.py index 8a835a1..c243018 100644 --- a/ConfigReader/AppConnectionsTestCases.py +++ b/ConfigReader/AppConnectionsTestCases.py @@ -77,7 +77,6 @@ def test_app_connections_base_type(self): with self.assertRaises(InvalidAppConnectionType): app_conn = AppConnections("123", "123", BaseAppConnectionPathType()) - def test_app_connections_actuator_type(self): """ Create a app connection where the path type is actuator, no error @@ -92,6 +91,94 @@ def test_app_connections_control_type(self): """ app_conn = AppConnections("123", "123", ControlAppConnectionPathType()) + def test_eq_equal(self): + """ + Compare two app cons that have the sender, receiver and path type being equal. + :return: + """ + ac1 = AppConnections("123", "123", ControlAppConnectionPathType()) + ac2 = AppConnections("123", "123", ControlAppConnectionPathType()) + self.assertTrue(ac1 == ac2) + + ac1 = AppConnections("321", "123", ActuatorAppConnectionPathType()) + ac2 = AppConnections("321", "123", ActuatorAppConnectionPathType()) + self.assertTrue(ac1 == ac2) + + def test_eq_not_equal_sender(self): + """ + Compare two app conns that do not have the same sender and test eq operator. + :return: + """ + ac1 = AppConnections("123", "123", ControlAppConnectionPathType()) + ac2 = AppConnections("321", "123", ControlAppConnectionPathType()) + self.assertFalse(ac1 == ac2) + + def test_eq_not_equal_receiver(self): + """ + Compare two app conns that do not have the same receiver and test eq operator. + :return: + """ + ac1 = AppConnections("123", "123", ControlAppConnectionPathType()) + ac2 = AppConnections("123", "321", ControlAppConnectionPathType()) + self.assertFalse(ac1 == ac2) + + def test_eq_not_equal_path_type(self): + """ + Compare two app conns that do not have the same path type and test eq operator. + :return: + """ + ac1 = AppConnections("123", "123", ControlAppConnectionPathType()) + ac2 = AppConnections("123", "123", ActuatorAppConnectionPathType()) + self.assertFalse(ac1 == ac2) + + ac1 = AppConnections("123", "123", ActuatorAppConnectionPathType()) + ac2 = AppConnections("123", "123", ControlAppConnectionPathType()) + self.assertFalse(ac1 == ac2) + + def test_ne_equal(self): + """ + Compare two equal app cons using not equal operator. + :return: + """ + ac1 = AppConnections("123", "123", ControlAppConnectionPathType()) + ac2 = AppConnections("123", "123", ControlAppConnectionPathType()) + self.assertFalse(ac1 != ac2) + + ac1 = AppConnections("321", "123", ActuatorAppConnectionPathType()) + ac2 = AppConnections("321", "123", ActuatorAppConnectionPathType()) + self.assertFalse(ac1 != ac2) + + def test_ne_not_equal_sender(self): + """ + Compare two not equal sender using the not equal operator. + :return: + """ + ac1 = AppConnections("123", "123", ControlAppConnectionPathType()) + ac2 = AppConnections("321", "123", ControlAppConnectionPathType()) + self.assertTrue(ac1 != ac2) + + def test_ne_not_equal_receiver(self): + """ + Compare two not equal receiver using the not equal operator. + :return: + """ + ac1 = AppConnections("123", "123", ControlAppConnectionPathType()) + ac2 = AppConnections("123", "321", ControlAppConnectionPathType()) + self.assertTrue(ac1 != ac2) + + def test_ne_not_equal_path_type(self): + """ + Compare two app conns that do not have the same path type and test != operator. + :return: + """ + ac1 = AppConnections("123", "123", ControlAppConnectionPathType()) + ac2 = AppConnections("123", "123", ActuatorAppConnectionPathType()) + self.assertTrue(ac1 != ac2) + + ac1 = AppConnections("123", "123", ActuatorAppConnectionPathType()) + ac2 = AppConnections("123", "123", ControlAppConnectionPathType()) + self.assertTrue(ac1 != ac2) + if __name__ == '__main__': unittest.main() diff --git a/ConfigReader/AppConnectionsTypes.py b/ConfigReader/AppConnectionsTypes.py index a33f9ec..4bc8362 100644 --- a/ConfigReader/AppConnectionsTypes.py +++ b/ConfigReader/AppConnectionsTypes.py @@ -16,7 +16,7 @@ class BaseAppConnectionPathType: The base app connection type. """ # Stores the type of the network connection - type = "base" + app_conn_type = "base" def __setattr__(self, key, value): """ @@ -27,16 +27,34 @@ def __setattr__(self, key, value): """ raise ImmutableObjectError + def __eq__(self, other): + """ + If the app_conn_type is equal, return true, otherwise false. + :param other: + :return: + """ + if isinstance(other, BaseAppConnectionPathType): + return self.app_conn_type == other.app_conn_type + return False + + def __ne__(self, other): + """ + If the app_conn_type is equal, return true, otherwise false. + :param other: + :return: + """ + return not self.__eq__(other) + class ControlAppConnectionPathType(BaseAppConnectionPathType): """ A control app connection path type """ - type = "control" + app_conn_type = "control" class ActuatorAppConnectionPathType(BaseAppConnectionPathType): """ A actuator app connection path type """ - type = "actuator" + app_conn_type = "actuator" diff --git a/ConfigReader/Config.py b/ConfigReader/Config.py index 8757ff6..28cbb2f 100644 --- a/ConfigReader/Config.py +++ b/ConfigReader/Config.py @@ -14,8 +14,10 @@ from ConfigErrors import InvalidNetworkType, NodeWithNetworkIdAlreadyExistsInNetwork, \ NodeWithPowerIdAlreadyExistsInNetwork, NodeInNetworkConnectionDoesNotExist, NetworkConnectionAlreadyExists, \ InvalidNetworkConnectionType, NoAccessPointFoundInNetworkConnection, NoNonAccessPointFoundInNetworkConnection, \ - NodeInNetworkConnectionDoesHaveCorrectNIC + NodeInNetworkConnectionDoesHaveCorrectNIC, NodeInAppConnectionDoesNotExist, InvalidAppConnectionType from NetworkConnection import NetworkConnection +from AppConnections import AppConnections +from AppConnectionsTypes import ControlAppConnectionPathType, ActuatorAppConnectionPathType from NetworkConnectionTypes import NetworkConnectionP2P, NetworkConnectionWiFi from NICs import P2PNIC, WiFiNIC from Node import Node @@ -39,8 +41,6 @@ class Config: __network_connection_ids = set() # Stores the app connections app_connections = [] - # Stores the app connection ids in a set, used for verification purposes - __app_connections = [] def __init__(self, file): """ @@ -86,6 +86,10 @@ def read_config(self): network_layout_dict = primary_network_dict["network_layout"] self.__read_network_connections(network_layout_dict) + # Loads the app connections + app_connections_dict = primary_network_dict["app_connections"] + self.__read_app_connections(app_connections_dict) + def __read_nodes_from_network(self, data): """ Reads the nodes from the primary network, parses them, then verifies them. @@ -140,12 +144,24 @@ def __read_network_connections(self, network_layout_dict): - Both nodes have correct type of NIC :return: """ - # Go through each connection and create a node from it + # Go through each connection for network_conn_dict in network_layout_dict: network_connection = self.__read_and_create_network_connections(network_conn_dict) self.network_connections.append(network_connection) self.__network_connection_ids.add(tuple(sorted([network_connection.nodes[0], network_connection.nodes[1]]))) + def __read_app_connections(self, app_connections_dict): + """ + Reads the app connections between nodes, parses them and verifies them. + - Both nodes exist in the app connection + :param app_connections_dict: + :return: + """ + # Go through each app connection + for app_conn_dict in app_connections_dict: + app_conn = self.__read_application_connections(app_conn_dict) + self.app_connections.append(app_conn) + def __read_and_create_network_connections(self, network_conn_dict): """ Reads a network connection, the nodes and the type, converts it to a NetworkConnection class, and verifies the @@ -211,6 +227,38 @@ def __read_and_create_network_connections(self, network_conn_dict): # Create a conn and return it return NetworkConnection([node_one, node_two], conn_type) + def __read_application_connections(self, app_conn_dict): + """ + Reads the application connections, validates the connections by making sure the nodes exist. It does not however + validate the network connection to determine reachability. + :return: + """ + # Get the nodes + sender = app_conn_dict["sender"] + receiver = app_conn_dict["receiver"] + + # Check the nodes exist + if sender not in self.__network_node_ids: + raise NodeInAppConnectionDoesNotExist(sender) + if receiver not in self.__network_node_ids: + raise NodeInAppConnectionDoesNotExist(receiver) + + # Get the nodes if they exist, or it'll never get to this point + sender_found = self.__get_node_with_network_id(sender) + receiver_found = self.__get_node_with_network_id(receiver) + + # Check if the connection path type is valid + path_type = None + if app_conn_dict["path_type"] == "control": + path_type = ControlAppConnectionPathType() + elif app_conn_dict["path_type"] == "actuator": + path_type = ActuatorAppConnectionPathType() + else: + raise InvalidAppConnectionType + + # Return an app connection type + return AppConnections(sender_found.network_id, receiver_found.network_id, path_type) + def __get_node_with_network_id(self, network_id): """ Returns the node with the passed in network id if found, else return None diff --git a/ConfigReader/ConfigErrors.py b/ConfigReader/ConfigErrors.py index 11dbd9f..e0ff87c 100644 --- a/ConfigReader/ConfigErrors.py +++ b/ConfigReader/ConfigErrors.py @@ -64,6 +64,11 @@ class NodeInNetworkConnectionDoesNotExist(Exception): pass +class NodeInAppConnectionDoesNotExist(Exception): + """Raised when a node in a applications connection does not exist part of the file.""" + pass + + class NodeInNetworkConnectionDoesHaveCorrectNIC(Exception): """Raised when a node in a network connection does not have the correct nic.""" pass diff --git a/ConfigReader/ConfigTestCases.py b/ConfigReader/ConfigTestCases.py index a94917a..8e5e3d5 100644 --- a/ConfigReader/ConfigTestCases.py +++ b/ConfigReader/ConfigTestCases.py @@ -14,9 +14,12 @@ from Node import Node from NICs import P2PNIC, WiFiNIC from NetworkConnection import NetworkConnection +from AppConnections import AppConnections +from AppConnectionsTypes import ControlAppConnectionPathType, ActuatorAppConnectionPathType from ConfigErrors import NodeWithNetworkIdAlreadyExistsInNetwork, NodeWithPowerIdAlreadyExistsInNetwork, \ InvalidNetworkType, NetworkConnectionAlreadyExists, NodeInNetworkConnectionDoesHaveCorrectNIC, \ - NoAccessPointFoundInNetworkConnection, NoNonAccessPointFoundInNetworkConnection, NodeInNetworkConnectionDoesNotExist + NoAccessPointFoundInNetworkConnection, NoNonAccessPointFoundInNetworkConnection, \ + NodeInNetworkConnectionDoesNotExist, NodeInAppConnectionDoesNotExist, InvalidAppConnectionType from NetworkConnectionTypes import NetworkConnectionP2P, NetworkConnectionWiFi @@ -217,6 +220,55 @@ def test_missing_network_id(self): self.__open_file_and_wait_to_raise("TestFiles/not_valid_network_missing_node.json", NodeInNetworkConnectionDoesNotExist) + def test_node_one_missing(self): + """ + Check to see if config reader will fail if node one in an app connection is missing. Error should be thrown. + :return: + """ + self.__open_file_and_wait_to_raise("TestFiles/not_valid_app_conn_node_one_missing.json", + NodeInAppConnectionDoesNotExist) + + def test_node_two_missing(self): + """ + Check to see if config reader will fail if node two in an app connection is missing. Error should be thrown. + :return: + """ + self.__open_file_and_wait_to_raise("TestFiles/not_valid_app_conn_node_two_missing.json", + NodeInAppConnectionDoesNotExist) + + def test_wrong_connection_types(self): + """ + Will pass in invalid path type of app connections, errors should be thrown. + :return: + """ + self.__open_file_and_wait_to_raise("TestFiles/not_valid_app_conn_wrong_path_type_one.json", + InvalidAppConnectionType) + self.__open_file_and_wait_to_raise("TestFiles/not_valid_app_conn_wrong_path_type_two.json", + InvalidAppConnectionType) + + def test_valid_app_connection(self): + """ + Will pass in valid app connections of different types. Should work. + :return: + """ + valid_app_conns_list = [ + AppConnections("-111", "-222", ControlAppConnectionPathType()), + AppConnections("-333", "-444", ActuatorAppConnectionPathType()) + ] + # Read the file + file = open("TestFiles/valid_app_conns.json") + config = Config(file) + config.read_config() + # Should have read 3 nodes + self.assertEqual(len(config.app_connections), len(valid_app_conns_list)) + + # Iterate through the nodes to check their properties + for i in range(0, len(valid_app_conns_list)): + self.assertTrue(valid_app_conns_list[i] == config.app_connections[i]) + + # Close the file + file.close() + if __name__ == '__main__': unittest.main() diff --git a/ConfigReader/Node.py b/ConfigReader/Node.py index 41a4d46..3c449f6 100644 --- a/ConfigReader/Node.py +++ b/ConfigReader/Node.py @@ -81,26 +81,26 @@ def __setattr__(self, key, value): """ raise ImmutableObjectError - def __has_type_of_card(self, type): + def __has_type_of_card(self, card_type): """ Check to see if Node has a type of card in nic_types - :param type: + :param card_type: :return: """ - if len(self.__get_type_of_cards(type)) > 0: + if len(self.__get_type_of_cards(card_type)) > 0: return True else: return False - def __get_type_of_cards(self, type): + def __get_type_of_cards(self, card_type): """ Gets and returns all the cards of type, well type - :param type: + :param card_type: :return: """ to_return = [] for card in self.nic_types: - if isinstance(card, type): + if isinstance(card, card_type): to_return.append(card) return to_return diff --git a/ConfigReader/NodeTestCases.py b/ConfigReader/NodeTestCases.py index d5f34fa..f4095e0 100644 --- a/ConfigReader/NodeTestCases.py +++ b/ConfigReader/NodeTestCases.py @@ -283,6 +283,5 @@ def test_is_wifi_access_point(self): n = Node("test", "test", {"x": "321", "y": "321"}, [WiFiNIC(access_point=True)]) self.assertTrue(n.is_wifi_access_point()) - if __name__ == '__main__': unittest.main() diff --git a/ConfigReader/TestFiles/not_valid_app_conn_node_one_missing.json b/ConfigReader/TestFiles/not_valid_app_conn_node_one_missing.json new file mode 100644 index 0000000..8631b33 --- /dev/null +++ b/ConfigReader/TestFiles/not_valid_app_conn_node_one_missing.json @@ -0,0 +1,52 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "1111111111", + "power_network_id": "11111111100", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "p2p" + }, + { + "type": "wifi", + "access_point": true + } + ] + }, + { + "id": "1111111112", + "power_network_id": "11111111101", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "1111111111", + "1111111112" + ], + "type": "p2p" + } + ], + "app_connections": [ + { + "receiver": "1111111111", + "sender": "1111111113", + "path_type": "control" + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/not_valid_app_conn_node_two_missing.json b/ConfigReader/TestFiles/not_valid_app_conn_node_two_missing.json new file mode 100644 index 0000000..c1d1ebd --- /dev/null +++ b/ConfigReader/TestFiles/not_valid_app_conn_node_two_missing.json @@ -0,0 +1,52 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "1111111", + "power_network_id": "11111100", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "p2p" + }, + { + "type": "wifi", + "access_point": true + } + ] + }, + { + "id": "1111112", + "power_network_id": "11111101", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "1111111", + "1111112" + ], + "type": "p2p" + } + ], + "app_connections": [ + { + "receiver": "1111113", + "sender": "1111112", + "path_type": "control" + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/not_valid_app_conn_wrong_path_type_one.json b/ConfigReader/TestFiles/not_valid_app_conn_wrong_path_type_one.json new file mode 100644 index 0000000..28c1196 --- /dev/null +++ b/ConfigReader/TestFiles/not_valid_app_conn_wrong_path_type_one.json @@ -0,0 +1,52 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "11111112222", + "power_network_id": "222211111100", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "p2p" + }, + { + "type": "wifi", + "access_point": true + } + ] + }, + { + "id": "11111122222", + "power_network_id": "222211111101", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "11111112222", + "11111122222" + ], + "type": "p2p" + } + ], + "app_connections": [ + { + "receiver": "11111112222", + "sender": "11111122222", + "path_type": "controller" + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/not_valid_app_conn_wrong_path_type_two.json b/ConfigReader/TestFiles/not_valid_app_conn_wrong_path_type_two.json new file mode 100644 index 0000000..3ed3549 --- /dev/null +++ b/ConfigReader/TestFiles/not_valid_app_conn_wrong_path_type_two.json @@ -0,0 +1,52 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "111111122222", + "power_network_id": "2222111111002", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "p2p" + }, + { + "type": "wifi", + "access_point": true + } + ] + }, + { + "id": "111111222222", + "power_network_id": "2222111111012", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "111111122222", + "111111222222" + ], + "type": "p2p" + } + ], + "app_connections": [ + { + "receiver": "111111122222", + "sender": "111111222222", + "path_type": "actuatorr" + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/valid_app_conns.json b/ConfigReader/TestFiles/valid_app_conns.json new file mode 100644 index 0000000..9ceb5c7 --- /dev/null +++ b/ConfigReader/TestFiles/valid_app_conns.json @@ -0,0 +1,94 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "-111", + "power_network_id": "-1111", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "p2p" + }, + { + "type": "wifi", + "access_point": true + } + ] + }, + { + "id": "-222", + "power_network_id": "-2222", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + }, + { + "id": "-333", + "power_network_id": "-3333", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "p2p" + }, + { + "type": "wifi", + "access_point": true + } + ] + }, + { + "id": "-444", + "power_network_id": "-4444", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "-111", + "-222" + ], + "type": "p2p" + }, + { + "nodes": [ + "-333", + "-444" + ], + "type": "p2p" + } + ], + "app_connections": [ + { + "sender": "-111", + "receiver": "-222", + "path_type": "control" + }, + { + "sender": "-333", + "receiver": "-444", + "path_type": "actuator" + } + ] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/valid_network_connections_mixed.json b/ConfigReader/TestFiles/valid_network_connections_mixed.json index 582d281..acdeac0 100644 --- a/ConfigReader/TestFiles/valid_network_connections_mixed.json +++ b/ConfigReader/TestFiles/valid_network_connections_mixed.json @@ -118,6 +118,7 @@ ], "type": "wifi" } - ] + ], + "app_connections": [] } } \ No newline at end of file diff --git a/ConfigReader/TestFiles/valid_network_connections_p2p.json b/ConfigReader/TestFiles/valid_network_connections_p2p.json index 7d19e94..de6d95f 100644 --- a/ConfigReader/TestFiles/valid_network_connections_p2p.json +++ b/ConfigReader/TestFiles/valid_network_connections_p2p.json @@ -103,6 +103,7 @@ ], "type": "p2p" } - ] + ], + "app_connections": [] } } \ No newline at end of file diff --git a/ConfigReader/TestFiles/valid_network_connections_wifi.json b/ConfigReader/TestFiles/valid_network_connections_wifi.json index a136709..ba63840 100644 --- a/ConfigReader/TestFiles/valid_network_connections_wifi.json +++ b/ConfigReader/TestFiles/valid_network_connections_wifi.json @@ -94,6 +94,7 @@ ], "type": "wifi" } - ] + ], + "app_connections": [] } } \ No newline at end of file diff --git a/ConfigReader/TestFiles/valid_nodes.json b/ConfigReader/TestFiles/valid_nodes.json index 9535ae3..cc457c2 100644 --- a/ConfigReader/TestFiles/valid_nodes.json +++ b/ConfigReader/TestFiles/valid_nodes.json @@ -43,6 +43,7 @@ }] } ], - "network_layout": [] + "network_layout": [], + "app_connections": [] } } \ No newline at end of file From 2642bdae71f192c45ba4a6bb4cf7273d37135928 Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Wed, 12 Aug 2020 18:29:07 -0600 Subject: [PATCH 19/22] Config Validation for wifi nodes distance and tests finished. - When config reads a wifi ap/non-ap pair. Check to see if the distance is equal to or more than 50m, if distance is not less than 50m, an error is thrown. - Tests added to test distance validation. --- ConfigReader/Config.py | 7 +- ConfigReader/ConfigErrors.py | 5 ++ ConfigReader/ConfigHelpers.py | 69 +++++++++++++++++++ ConfigReader/ConfigTestCases.py | 35 +++++++++- ConfigReader/Node.py | 2 +- ...lid_network_connections_distance_wifi.json | 44 ++++++++++++ .../not_valid_network_duplicate_wifi.json | 2 +- ...alid_network_connections_distance_p2p.json | 42 +++++++++++ ...lid_network_connections_distance_wifi.json | 44 ++++++++++++ .../valid_network_connections_mixed.json | 20 +++--- .../valid_network_connections_wifi.json | 20 +++--- ConfigReader/ValidationFunctions.py | 23 +++++++ 12 files changed, 289 insertions(+), 24 deletions(-) create mode 100644 ConfigReader/ConfigHelpers.py create mode 100644 ConfigReader/TestFiles/invalid_network_connections_distance_wifi.json create mode 100644 ConfigReader/TestFiles/valid_network_connections_distance_p2p.json create mode 100644 ConfigReader/TestFiles/valid_network_connections_distance_wifi.json diff --git a/ConfigReader/Config.py b/ConfigReader/Config.py index 28cbb2f..5b7e6a9 100644 --- a/ConfigReader/Config.py +++ b/ConfigReader/Config.py @@ -14,13 +14,15 @@ from ConfigErrors import InvalidNetworkType, NodeWithNetworkIdAlreadyExistsInNetwork, \ NodeWithPowerIdAlreadyExistsInNetwork, NodeInNetworkConnectionDoesNotExist, NetworkConnectionAlreadyExists, \ InvalidNetworkConnectionType, NoAccessPointFoundInNetworkConnection, NoNonAccessPointFoundInNetworkConnection, \ - NodeInNetworkConnectionDoesHaveCorrectNIC, NodeInAppConnectionDoesNotExist, InvalidAppConnectionType + NodeInNetworkConnectionDoesHaveCorrectNIC, NodeInAppConnectionDoesNotExist, InvalidAppConnectionType, \ + NodeTooFarAwayFromAccessPoint from NetworkConnection import NetworkConnection from AppConnections import AppConnections from AppConnectionsTypes import ControlAppConnectionPathType, ActuatorAppConnectionPathType from NetworkConnectionTypes import NetworkConnectionP2P, NetworkConnectionWiFi from NICs import P2PNIC, WiFiNIC from Node import Node +from ValidationFunctions import check_distance_between_wifi_access_point_and_node class Config: @@ -221,6 +223,9 @@ def __read_and_create_network_connections(self, network_conn_dict): if not found_access_point: raise NoAccessPointFoundInNetworkConnection(str(node_one_found), str(node_two_found)) + + if not check_distance_between_wifi_access_point_and_node([node_one_found, node_two_found]): + raise NodeTooFarAwayFromAccessPoint else: raise InvalidNetworkConnectionType(network_conn_dict["type"]) diff --git a/ConfigReader/ConfigErrors.py b/ConfigReader/ConfigErrors.py index e0ff87c..9ab54ea 100644 --- a/ConfigReader/ConfigErrors.py +++ b/ConfigReader/ConfigErrors.py @@ -87,3 +87,8 @@ class NoAccessPointFoundInNetworkConnection(Exception): class NoNonAccessPointFoundInNetworkConnection(Exception): """Raised when two wifi nodes are connected but a non-access-point has not been found.""" pass + + +class NodeTooFarAwayFromAccessPoint(Exception): + """Raised when a wifi node and an access point are too far away, for now that is 50m or more.""" + pass diff --git a/ConfigReader/ConfigHelpers.py b/ConfigReader/ConfigHelpers.py new file mode 100644 index 0000000..69ec87e --- /dev/null +++ b/ConfigReader/ConfigHelpers.py @@ -0,0 +1,69 @@ +""" +Created on August 12, 2020 +File contains helper for the config readers/validators. + +@file ConfigHelpers.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.08.12 +@version 0.1 +@company University of Alberta - Computing Science +""" +from NICs import WiFiNIC + + +def find_access_point_in_wifi_nodes(nodes): + """ + Find and return the access point in the wifi nodes. + :param nodes: + :return: + """ + return get_wifi_node(True, nodes) + + +def find_non_access_point_in_wifi_nodes(nodes): + """ + Find and return the non access point in the wifi nodes. + :param nodes: + :return: + """ + return get_wifi_node(False, nodes) + + +def get_wifi_node(access_point, nodes): + """ + If access point is true, returns the access point from the nodes, if access point is false, returns the non access + point from the nodes. + :param access_point: + :param nodes: + :return: + """ + for node in nodes: + wifi_nic = get_nic_of_type(node.nic_types, WiFiNIC) + if wifi_nic.access_point == access_point: + return node + + return None + + +def get_nic_of_type(nics, nic_type): + """ + Go through nics and find the nic that is of type nic_type, otherwise throw a type error. + :param nics: + :param nic_type: + :return: + """ + for nic in nics: + if isinstance(nic, nic_type): + return nic + + raise TypeError(str(nic_type) + " not found in " + str(nics)) + + +def check_if_node_is_of_type(node, node_type): + """ + Check if a node is of type passed in. + :return: + """ + if not isinstance(node, node_type): + raise TypeError(str(node) + " is not of type " + str(node_type)) diff --git a/ConfigReader/ConfigTestCases.py b/ConfigReader/ConfigTestCases.py index 8e5e3d5..1cf8395 100644 --- a/ConfigReader/ConfigTestCases.py +++ b/ConfigReader/ConfigTestCases.py @@ -19,7 +19,8 @@ from ConfigErrors import NodeWithNetworkIdAlreadyExistsInNetwork, NodeWithPowerIdAlreadyExistsInNetwork, \ InvalidNetworkType, NetworkConnectionAlreadyExists, NodeInNetworkConnectionDoesHaveCorrectNIC, \ NoAccessPointFoundInNetworkConnection, NoNonAccessPointFoundInNetworkConnection, \ - NodeInNetworkConnectionDoesNotExist, NodeInAppConnectionDoesNotExist, InvalidAppConnectionType + NodeInNetworkConnectionDoesNotExist, NodeInAppConnectionDoesNotExist, InvalidAppConnectionType, \ + NodeTooFarAwayFromAccessPoint from NetworkConnectionTypes import NetworkConnectionP2P, NetworkConnectionWiFi @@ -269,6 +270,38 @@ def test_valid_app_connection(self): # Close the file file.close() + def test_distance_too_far_p2p(self): + """ + In this case, the distance should not matter. The layout should be valid. + :return: + """ + file = open("TestFiles/valid_network_connections_distance_p2p.json") + config = Config(file) + config.read_config() + file.close() + + def test_distance_too_far_wifi(self): + """ + In this case, distance should matter, should get an exception. + :return: + """ + file = open("TestFiles/invalid_network_connections_distance_wifi.json") + config = Config(file) + + with self.assertRaises(NodeTooFarAwayFromAccessPoint): + config.read_config() + + file.close() + + def test_distance_close_enough_wifi(self): + """ + In this case, distance should matter, but should be valid. + :return: + """ + file = open("TestFiles/valid_network_connections_distance_wifi.json") + config = Config(file) + config.read_config() + file.close() if __name__ == '__main__': unittest.main() diff --git a/ConfigReader/Node.py b/ConfigReader/Node.py index 3c449f6..228187b 100644 --- a/ConfigReader/Node.py +++ b/ConfigReader/Node.py @@ -41,7 +41,7 @@ def __init__(self, power_id, network_id, location, nic_types): super(Node, self).__setattr__('power_id', power_id) super(Node, self).__setattr__('network_id', network_id) - super(Node, self).__setattr__('location', location) + super(Node, self).__setattr__('location', {'x': float(location['x']), 'y': float(location['y'])}) super(Node, self).__setattr__('nic_types', nic_types) def has_p2p_card(self): diff --git a/ConfigReader/TestFiles/invalid_network_connections_distance_wifi.json b/ConfigReader/TestFiles/invalid_network_connections_distance_wifi.json new file mode 100644 index 0000000..2bd303f --- /dev/null +++ b/ConfigReader/TestFiles/invalid_network_connections_distance_wifi.json @@ -0,0 +1,44 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "-1111819", + "power_network_id": "-11118009", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": true + } + ] + }, + { + "id": "-1111829", + "power_network_id": "-11181019", + "location": { + "x": "200", + "y": "349" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": false + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "-1111819", + "-1111829" + ], + "type": "wifi" + } + ], + "app_connections": [] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/not_valid_network_duplicate_wifi.json b/ConfigReader/TestFiles/not_valid_network_duplicate_wifi.json index b118e7b..ffd5af9 100644 --- a/ConfigReader/TestFiles/not_valid_network_duplicate_wifi.json +++ b/ConfigReader/TestFiles/not_valid_network_duplicate_wifi.json @@ -20,7 +20,7 @@ "power_network_id": "146", "location": { "x": "200", - "y": "350" + "y": "410" }, "nic_card_types": [ { diff --git a/ConfigReader/TestFiles/valid_network_connections_distance_p2p.json b/ConfigReader/TestFiles/valid_network_connections_distance_p2p.json new file mode 100644 index 0000000..3840ba5 --- /dev/null +++ b/ConfigReader/TestFiles/valid_network_connections_distance_p2p.json @@ -0,0 +1,42 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "-11111", + "power_network_id": "-111100", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + }, + { + "id": "-11112", + "power_network_id": "-111101", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "p2p" + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "-11111", + "-11112" + ], + "type": "p2p" + } + ], + "app_connections": [] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/valid_network_connections_distance_wifi.json b/ConfigReader/TestFiles/valid_network_connections_distance_wifi.json new file mode 100644 index 0000000..9df09a2 --- /dev/null +++ b/ConfigReader/TestFiles/valid_network_connections_distance_wifi.json @@ -0,0 +1,44 @@ +{ + "primary_network": { + "nodes": [ + { + "id": "-111181", + "power_network_id": "-1111800", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": true + } + ] + }, + { + "id": "-111182", + "power_network_id": "-1118101", + "location": { + "x": "200", + "y": "351" + }, + "nic_card_types": [ + { + "type": "wifi", + "access_point": false + } + ] + } + ], + "network_layout": [ + { + "nodes": [ + "-111181", + "-111182" + ], + "type": "wifi" + } + ], + "app_connections": [] + } +} \ No newline at end of file diff --git a/ConfigReader/TestFiles/valid_network_connections_mixed.json b/ConfigReader/TestFiles/valid_network_connections_mixed.json index acdeac0..d374148 100644 --- a/ConfigReader/TestFiles/valid_network_connections_mixed.json +++ b/ConfigReader/TestFiles/valid_network_connections_mixed.json @@ -5,8 +5,8 @@ "id": "1111", "power_network_id": "11100", "location": { - "x": "200", - "y": "400" + "x": "0", + "y": "0" }, "nic_card_types": [ { @@ -22,8 +22,8 @@ "id": "1112", "power_network_id": "11101", "location": { - "x": "200", - "y": "350" + "x": "10", + "y": "10" }, "nic_card_types": [ { @@ -35,8 +35,8 @@ "id": "1113", "power_network_id": "11102", "location": { - "x": "200", - "y": "300" + "x": "20", + "y": "20" }, "nic_card_types": [ { @@ -48,8 +48,8 @@ "id": "1114", "power_network_id": "11103", "location": { - "x": "0", - "y": "250" + "x": "30", + "y": "30" }, "nic_card_types": [ { @@ -61,8 +61,8 @@ "id": "1115", "power_network_id": "11104", "location": { - "x": "100", - "y": "250" + "x": "40", + "y": "10" }, "nic_card_types": [ { diff --git a/ConfigReader/TestFiles/valid_network_connections_wifi.json b/ConfigReader/TestFiles/valid_network_connections_wifi.json index ba63840..ddc51bb 100644 --- a/ConfigReader/TestFiles/valid_network_connections_wifi.json +++ b/ConfigReader/TestFiles/valid_network_connections_wifi.json @@ -5,8 +5,8 @@ "id": "21", "power_network_id": "110", "location": { - "x": "200", - "y": "400" + "x": "0", + "y": "0" }, "nic_card_types": [ { @@ -19,8 +19,8 @@ "id": "22", "power_network_id": "111", "location": { - "x": "200", - "y": "350" + "x": "10", + "y": "10" }, "nic_card_types": [ { @@ -33,8 +33,8 @@ "id": "23", "power_network_id": "112", "location": { - "x": "200", - "y": "300" + "x": "20", + "y": "20" }, "nic_card_types": [ { @@ -47,8 +47,8 @@ "id": "24", "power_network_id": "113", "location": { - "x": "0", - "y": "250" + "x": "30", + "y": "30" }, "nic_card_types": [ { @@ -61,8 +61,8 @@ "id": "25", "power_network_id": "114", "location": { - "x": "110", - "y": "250" + "x": "40", + "y": "10" }, "nic_card_types": [ { diff --git a/ConfigReader/ValidationFunctions.py b/ConfigReader/ValidationFunctions.py index 5a7e699..3b5127b 100644 --- a/ConfigReader/ValidationFunctions.py +++ b/ConfigReader/ValidationFunctions.py @@ -16,6 +16,8 @@ from NICs import P2PNIC, WiFiNIC from NetworkConnectionTypes import NetworkConnectionWiFi, NetworkConnectionP2P from AppConnectionsTypes import ControlAppConnectionPathType, ActuatorAppConnectionPathType +from math import sqrt +from ConfigHelpers import find_access_point_in_wifi_nodes, find_non_access_point_in_wifi_nodes # Stores the valid types of nics valid_nic_types = [P2PNIC, WiFiNIC] @@ -127,3 +129,24 @@ def check_network_connection_nodes(nodes): # Now make sure every node is valid for node in nodes: check_non_empty_non_none_string(node) + + +def check_distance_between_wifi_access_point_and_node(nodes): + """ + Check the distance between ap and node to make sure it is less than 50m. + :param nodes: + :return: + """ + # Make sure there are only two nodes in nodes + if len(nodes) != 2: + raise NetworkConnectionNumberOfNodesNotCorrect + + ap = find_access_point_in_wifi_nodes(nodes) + node = find_non_access_point_in_wifi_nodes(nodes) + + distance = sqrt(((ap.location['x'] - node.location['x']) ** 2) + ((ap.location['y'] - node.location['y']) ** 2)) + + if distance < 50: + return True + else: + return False From 5bc9d9de76ed826be9a07fbd53863062f29f199f Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Mon, 17 Aug 2020 12:38:31 -0600 Subject: [PATCH 20/22] Folder re-org and Consisntent date format - Re-orged the files - Changed all the dates in the config folder to be YYYY.MM.DD --- config/generator/ConfigGenerator.py | 11 ++++++++++ .../reader}/AppConnections.py | 2 +- .../reader}/AppConnectionsTypes.py | 0 {ConfigReader => config/reader}/Config.py | 20 +++++++++--------- .../reader}/ConfigErrors.py | 0 .../reader}/ConfigHelpers.py | 2 +- {ConfigReader => config/reader}/NICs.py | 2 +- .../reader}/NetworkConnection.py | 4 ++-- .../reader}/NetworkConnectionTypes.py | 0 {ConfigReader => config/reader}/Node.py | 7 ++++--- .../reader}/ValidationFunctions.py | 10 ++++----- .../reader/tests}/AppConnectionsTestCases.py | 7 ++++--- .../reader/tests}/ConfigTestCases.py | 21 ++++++++++--------- .../reader/tests}/NICTestCases.py | 4 ++-- .../tests}/NetworkConnectionTestCases.py | 8 +++---- .../reader/tests}/NodeTestCases.py | 6 +++--- .../TestFiles/duplicate_network_id_nodes.json | 0 .../TestFiles/duplicate_power_id_nodes.json | 0 ...lid_network_connections_distance_wifi.json | 0 .../not_valid_app_conn_node_one_missing.json | 0 .../not_valid_app_conn_node_two_missing.json | 0 ...ot_valid_app_conn_wrong_path_type_one.json | 0 ...ot_valid_app_conn_wrong_path_type_two.json | 0 .../not_valid_network_duplicate_mixed.json | 0 .../not_valid_network_duplicate_p2p.json | 0 .../not_valid_network_duplicate_wifi.json | 0 .../not_valid_network_missing_nic_p2p.json | 0 .../not_valid_network_missing_nic_wifi.json | 0 .../not_valid_network_missing_node.json | 0 ...ot_valid_network_wifi_no_access_point.json | 0 ...alid_network_wifi_no_non_access_point.json | 0 .../tests}/TestFiles/valid_app_conns.json | 0 ...alid_network_connections_distance_p2p.json | 0 ...lid_network_connections_distance_wifi.json | 0 .../valid_network_connections_mixed.json | 0 .../valid_network_connections_p2p.json | 0 .../valid_network_connections_wifi.json | 0 .../reader/tests}/TestFiles/valid_nodes.json | 0 .../tests}/TestFiles/wrong_type_nic.json | 0 39 files changed, 59 insertions(+), 45 deletions(-) create mode 100644 config/generator/ConfigGenerator.py rename {ConfigReader => config/reader}/AppConnections.py (95%) rename {ConfigReader => config/reader}/AppConnectionsTypes.py (100%) rename {ConfigReader => config/reader}/Config.py (94%) rename {ConfigReader => config/reader}/ConfigErrors.py (100%) rename {ConfigReader => config/reader}/ConfigHelpers.py (97%) rename {ConfigReader => config/reader}/NICs.py (98%) rename {ConfigReader => config/reader}/NetworkConnection.py (93%) rename {ConfigReader => config/reader}/NetworkConnectionTypes.py (100%) rename {ConfigReader => config/reader}/Node.py (95%) rename {ConfigReader => config/reader}/ValidationFunctions.py (90%) rename {ConfigReader => config/reader/tests}/AppConnectionsTestCases.py (96%) rename {ConfigReader => config/reader/tests}/ConfigTestCases.py (95%) rename {ConfigReader => config/reader/tests}/NICTestCases.py (96%) rename {ConfigReader => config/reader/tests}/NetworkConnectionTestCases.py (95%) rename {ConfigReader => config/reader/tests}/NodeTestCases.py (98%) rename {ConfigReader => config/reader/tests}/TestFiles/duplicate_network_id_nodes.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/duplicate_power_id_nodes.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/invalid_network_connections_distance_wifi.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/not_valid_app_conn_node_one_missing.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/not_valid_app_conn_node_two_missing.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/not_valid_app_conn_wrong_path_type_one.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/not_valid_app_conn_wrong_path_type_two.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/not_valid_network_duplicate_mixed.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/not_valid_network_duplicate_p2p.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/not_valid_network_duplicate_wifi.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/not_valid_network_missing_nic_p2p.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/not_valid_network_missing_nic_wifi.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/not_valid_network_missing_node.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/not_valid_network_wifi_no_access_point.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/not_valid_network_wifi_no_non_access_point.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/valid_app_conns.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/valid_network_connections_distance_p2p.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/valid_network_connections_distance_wifi.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/valid_network_connections_mixed.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/valid_network_connections_p2p.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/valid_network_connections_wifi.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/valid_nodes.json (100%) rename {ConfigReader => config/reader/tests}/TestFiles/wrong_type_nic.json (100%) diff --git a/config/generator/ConfigGenerator.py b/config/generator/ConfigGenerator.py new file mode 100644 index 0000000..c38a3f6 --- /dev/null +++ b/config/generator/ConfigGenerator.py @@ -0,0 +1,11 @@ +""" +Created on August 30, 2020 +File contains the classes that will read and verify the config files. + +@file Config.py +@author Amrinder S. Grewal +@email asgrewal@ualberta.ca +@date 2020.08.06 +@version 0.1 +@company University of Alberta - Computing Science +""" \ No newline at end of file diff --git a/ConfigReader/AppConnections.py b/config/reader/AppConnections.py similarity index 95% rename from ConfigReader/AppConnections.py rename to config/reader/AppConnections.py index 976943e..4f998b2 100644 --- a/ConfigReader/AppConnections.py +++ b/config/reader/AppConnections.py @@ -10,7 +10,7 @@ @company University of Alberta - Computing Science """ -from ValidationFunctions import check_non_empty_non_none_string, check_app_connection_types +from config.reader.ValidationFunctions import check_non_empty_non_none_string, check_app_connection_types class AppConnections: diff --git a/ConfigReader/AppConnectionsTypes.py b/config/reader/AppConnectionsTypes.py similarity index 100% rename from ConfigReader/AppConnectionsTypes.py rename to config/reader/AppConnectionsTypes.py diff --git a/ConfigReader/Config.py b/config/reader/Config.py similarity index 94% rename from ConfigReader/Config.py rename to config/reader/Config.py index 5b7e6a9..de47bf4 100644 --- a/ConfigReader/Config.py +++ b/config/reader/Config.py @@ -1,28 +1,28 @@ """ -Created on August 30, 2020 +Created on July 30, 2020 File contains the classes that will read and verify the config files. @file Config.py @author Amrinder S. Grewal @email asgrewal@ualberta.ca -@date 2020.08.06 +@date 2020.07.30 @version 0.1 @company University of Alberta - Computing Science """ import json -from ConfigErrors import InvalidNetworkType, NodeWithNetworkIdAlreadyExistsInNetwork, \ +from config.reader.ConfigErrors import InvalidNetworkType, NodeWithNetworkIdAlreadyExistsInNetwork, \ NodeWithPowerIdAlreadyExistsInNetwork, NodeInNetworkConnectionDoesNotExist, NetworkConnectionAlreadyExists, \ InvalidNetworkConnectionType, NoAccessPointFoundInNetworkConnection, NoNonAccessPointFoundInNetworkConnection, \ NodeInNetworkConnectionDoesHaveCorrectNIC, NodeInAppConnectionDoesNotExist, InvalidAppConnectionType, \ NodeTooFarAwayFromAccessPoint -from NetworkConnection import NetworkConnection -from AppConnections import AppConnections -from AppConnectionsTypes import ControlAppConnectionPathType, ActuatorAppConnectionPathType -from NetworkConnectionTypes import NetworkConnectionP2P, NetworkConnectionWiFi -from NICs import P2PNIC, WiFiNIC -from Node import Node -from ValidationFunctions import check_distance_between_wifi_access_point_and_node +from config.reader.NetworkConnection import NetworkConnection +from config.reader.AppConnections import AppConnections +from config.reader.AppConnectionsTypes import ControlAppConnectionPathType, ActuatorAppConnectionPathType +from config.reader.NetworkConnectionTypes import NetworkConnectionP2P, NetworkConnectionWiFi +from config.reader.NICs import P2PNIC, WiFiNIC +from config.reader.Node import Node +from config.reader.ValidationFunctions import check_distance_between_wifi_access_point_and_node class Config: diff --git a/ConfigReader/ConfigErrors.py b/config/reader/ConfigErrors.py similarity index 100% rename from ConfigReader/ConfigErrors.py rename to config/reader/ConfigErrors.py diff --git a/ConfigReader/ConfigHelpers.py b/config/reader/ConfigHelpers.py similarity index 97% rename from ConfigReader/ConfigHelpers.py rename to config/reader/ConfigHelpers.py index 69ec87e..d4d9d6b 100644 --- a/ConfigReader/ConfigHelpers.py +++ b/config/reader/ConfigHelpers.py @@ -9,7 +9,7 @@ @version 0.1 @company University of Alberta - Computing Science """ -from NICs import WiFiNIC +from config.reader.NICs import WiFiNIC def find_access_point_in_wifi_nodes(nodes): diff --git a/ConfigReader/NICs.py b/config/reader/NICs.py similarity index 98% rename from ConfigReader/NICs.py rename to config/reader/NICs.py index 17dba34..b91458c 100644 --- a/ConfigReader/NICs.py +++ b/config/reader/NICs.py @@ -9,7 +9,7 @@ @version 0.1 @company University of Alberta - Computing Science """ -from ConfigErrors import ImmutableObjectError +from config.reader.ConfigErrors import ImmutableObjectError class NIC: diff --git a/ConfigReader/NetworkConnection.py b/config/reader/NetworkConnection.py similarity index 93% rename from ConfigReader/NetworkConnection.py rename to config/reader/NetworkConnection.py index 866c885..e28669a 100644 --- a/ConfigReader/NetworkConnection.py +++ b/config/reader/NetworkConnection.py @@ -10,8 +10,8 @@ @company University of Alberta - Computing Science """ -from ConfigErrors import ImmutableObjectError -from ValidationFunctions import check_network_connection_nodes, check_network_connection_types +from config.reader.ConfigErrors import ImmutableObjectError +from config.reader.ValidationFunctions import check_network_connection_nodes, check_network_connection_types class NetworkConnection: diff --git a/ConfigReader/NetworkConnectionTypes.py b/config/reader/NetworkConnectionTypes.py similarity index 100% rename from ConfigReader/NetworkConnectionTypes.py rename to config/reader/NetworkConnectionTypes.py diff --git a/ConfigReader/Node.py b/config/reader/Node.py similarity index 95% rename from ConfigReader/Node.py rename to config/reader/Node.py index 228187b..a748646 100644 --- a/ConfigReader/Node.py +++ b/config/reader/Node.py @@ -10,9 +10,10 @@ @company University of Alberta - Computing Science """ -from ConfigErrors import ImmutableObjectError -from ValidationFunctions import check_location_coordinates, check_non_empty_non_none_string, check_nic_types -from NICs import P2PNIC, WiFiNIC +from config.reader.ConfigErrors import ImmutableObjectError +from config.reader.ValidationFunctions import check_location_coordinates, check_non_empty_non_none_string, \ + check_nic_types +from config.reader.NICs import P2PNIC, WiFiNIC class Node: """ diff --git a/ConfigReader/ValidationFunctions.py b/config/reader/ValidationFunctions.py similarity index 90% rename from ConfigReader/ValidationFunctions.py rename to config/reader/ValidationFunctions.py index 3b5127b..0079b6e 100644 --- a/ConfigReader/ValidationFunctions.py +++ b/config/reader/ValidationFunctions.py @@ -10,14 +10,14 @@ @company University of Alberta - Computing Science """ -from ConfigErrors import InvalidNetworkType, InvalidAccessPointValueForNICType, \ +from config.reader.ConfigErrors import InvalidNetworkType, InvalidAccessPointValueForNICType, \ NetworkConnectionNumberOfNodesNotCorrect, NetworkConnectionHasNodesWithConnectionToSelf, \ InvalidNetworkConnectionType, InvalidAppConnectionType -from NICs import P2PNIC, WiFiNIC -from NetworkConnectionTypes import NetworkConnectionWiFi, NetworkConnectionP2P -from AppConnectionsTypes import ControlAppConnectionPathType, ActuatorAppConnectionPathType +from config.reader.NICs import P2PNIC, WiFiNIC +from config.reader.NetworkConnectionTypes import NetworkConnectionWiFi, NetworkConnectionP2P +from config.reader.AppConnectionsTypes import ControlAppConnectionPathType, ActuatorAppConnectionPathType from math import sqrt -from ConfigHelpers import find_access_point_in_wifi_nodes, find_non_access_point_in_wifi_nodes +from config.reader.ConfigHelpers import find_access_point_in_wifi_nodes, find_non_access_point_in_wifi_nodes # Stores the valid types of nics valid_nic_types = [P2PNIC, WiFiNIC] diff --git a/ConfigReader/AppConnectionsTestCases.py b/config/reader/tests/AppConnectionsTestCases.py similarity index 96% rename from ConfigReader/AppConnectionsTestCases.py rename to config/reader/tests/AppConnectionsTestCases.py index c243018..1e4c8a7 100644 --- a/ConfigReader/AppConnectionsTestCases.py +++ b/config/reader/tests/AppConnectionsTestCases.py @@ -11,9 +11,10 @@ """ import unittest -from AppConnections import AppConnections -from AppConnectionsTypes import ControlAppConnectionPathType, ActuatorAppConnectionPathType, BaseAppConnectionPathType -from ConfigErrors import InvalidAppConnectionType +from config.reader.AppConnections import AppConnections +from config.reader.AppConnectionsTypes import ControlAppConnectionPathType, ActuatorAppConnectionPathType, \ + BaseAppConnectionPathType +from config.reader.ConfigErrors import InvalidAppConnectionType class AppConnectionsTestCases(unittest.TestCase): diff --git a/ConfigReader/ConfigTestCases.py b/config/reader/tests/ConfigTestCases.py similarity index 95% rename from ConfigReader/ConfigTestCases.py rename to config/reader/tests/ConfigTestCases.py index 1cf8395..2b3e12b 100644 --- a/ConfigReader/ConfigTestCases.py +++ b/config/reader/tests/ConfigTestCases.py @@ -1,27 +1,27 @@ """ -Created on August 30, 2020 +Created on July 30, 2020 File contains tests that will test the reading/verification of config files that are being read by Config @file ConfigTestCases.py @author Amrinder S. Grewal @email asgrewal@ualberta.ca -@date 2020.08.06 +@date 2020.07.30 @version 0.1 @company University of Alberta - Computing Science """ import unittest -from Config import Config -from Node import Node -from NICs import P2PNIC, WiFiNIC -from NetworkConnection import NetworkConnection -from AppConnections import AppConnections -from AppConnectionsTypes import ControlAppConnectionPathType, ActuatorAppConnectionPathType -from ConfigErrors import NodeWithNetworkIdAlreadyExistsInNetwork, NodeWithPowerIdAlreadyExistsInNetwork, \ +from config.reader.Config import Config +from config.reader.Node import Node +from config.reader.NICs import P2PNIC, WiFiNIC +from config.reader.NetworkConnection import NetworkConnection +from config.reader.AppConnections import AppConnections +from config.reader.AppConnectionsTypes import ControlAppConnectionPathType, ActuatorAppConnectionPathType +from config.reader.ConfigErrors import NodeWithNetworkIdAlreadyExistsInNetwork, NodeWithPowerIdAlreadyExistsInNetwork, \ InvalidNetworkType, NetworkConnectionAlreadyExists, NodeInNetworkConnectionDoesHaveCorrectNIC, \ NoAccessPointFoundInNetworkConnection, NoNonAccessPointFoundInNetworkConnection, \ NodeInNetworkConnectionDoesNotExist, NodeInAppConnectionDoesNotExist, InvalidAppConnectionType, \ NodeTooFarAwayFromAccessPoint -from NetworkConnectionTypes import NetworkConnectionP2P, NetworkConnectionWiFi +from config.reader.NetworkConnectionTypes import NetworkConnectionP2P, NetworkConnectionWiFi class ConfigTestCases(unittest.TestCase): @@ -303,5 +303,6 @@ def test_distance_close_enough_wifi(self): config.read_config() file.close() + if __name__ == '__main__': unittest.main() diff --git a/ConfigReader/NICTestCases.py b/config/reader/tests/NICTestCases.py similarity index 96% rename from ConfigReader/NICTestCases.py rename to config/reader/tests/NICTestCases.py index ba384e2..7bfe918 100644 --- a/ConfigReader/NICTestCases.py +++ b/config/reader/tests/NICTestCases.py @@ -12,8 +12,8 @@ import unittest -from NICs import NIC, P2PNIC, WiFiNIC -from ConfigErrors import ImmutableObjectError +from config.reader.NICs import NIC, P2PNIC, WiFiNIC +from config.reader.ConfigErrors import ImmutableObjectError class AllNICTestCases(unittest.TestCase): diff --git a/ConfigReader/NetworkConnectionTestCases.py b/config/reader/tests/NetworkConnectionTestCases.py similarity index 95% rename from ConfigReader/NetworkConnectionTestCases.py rename to config/reader/tests/NetworkConnectionTestCases.py index c5e1b58..3dd7745 100644 --- a/ConfigReader/NetworkConnectionTestCases.py +++ b/config/reader/tests/NetworkConnectionTestCases.py @@ -11,10 +11,10 @@ """ import unittest -from ConfigErrors import NetworkConnectionNumberOfNodesNotCorrect, NetworkConnectionHasNodesWithConnectionToSelf, \ - InvalidNetworkConnectionType -from NetworkConnection import NetworkConnection -from NetworkConnectionTypes import NetworkConnectionP2P, NetworkConnectionTypeBase, NetworkConnectionWiFi +from config.reader.ConfigErrors import NetworkConnectionNumberOfNodesNotCorrect, \ + NetworkConnectionHasNodesWithConnectionToSelf, InvalidNetworkConnectionType +from config.reader.NetworkConnection import NetworkConnection +from config.reader.NetworkConnectionTypes import NetworkConnectionP2P, NetworkConnectionTypeBase, NetworkConnectionWiFi class NetworkConnectionTestCases(unittest.TestCase): diff --git a/ConfigReader/NodeTestCases.py b/config/reader/tests/NodeTestCases.py similarity index 98% rename from ConfigReader/NodeTestCases.py rename to config/reader/tests/NodeTestCases.py index f4095e0..3fefa19 100644 --- a/ConfigReader/NodeTestCases.py +++ b/config/reader/tests/NodeTestCases.py @@ -11,9 +11,9 @@ """ import unittest -from Node import Node -from NICs import P2PNIC, WiFiNIC, NIC -from ConfigErrors import InvalidNetworkType, InvalidAccessPointValueForNICType +from config.reader.Node import Node +from config.reader.NICs import P2PNIC, WiFiNIC, NIC +from config.reader.ConfigErrors import InvalidNetworkType, InvalidAccessPointValueForNICType class NodeTestCases(unittest.TestCase): diff --git a/ConfigReader/TestFiles/duplicate_network_id_nodes.json b/config/reader/tests/TestFiles/duplicate_network_id_nodes.json similarity index 100% rename from ConfigReader/TestFiles/duplicate_network_id_nodes.json rename to config/reader/tests/TestFiles/duplicate_network_id_nodes.json diff --git a/ConfigReader/TestFiles/duplicate_power_id_nodes.json b/config/reader/tests/TestFiles/duplicate_power_id_nodes.json similarity index 100% rename from ConfigReader/TestFiles/duplicate_power_id_nodes.json rename to config/reader/tests/TestFiles/duplicate_power_id_nodes.json diff --git a/ConfigReader/TestFiles/invalid_network_connections_distance_wifi.json b/config/reader/tests/TestFiles/invalid_network_connections_distance_wifi.json similarity index 100% rename from ConfigReader/TestFiles/invalid_network_connections_distance_wifi.json rename to config/reader/tests/TestFiles/invalid_network_connections_distance_wifi.json diff --git a/ConfigReader/TestFiles/not_valid_app_conn_node_one_missing.json b/config/reader/tests/TestFiles/not_valid_app_conn_node_one_missing.json similarity index 100% rename from ConfigReader/TestFiles/not_valid_app_conn_node_one_missing.json rename to config/reader/tests/TestFiles/not_valid_app_conn_node_one_missing.json diff --git a/ConfigReader/TestFiles/not_valid_app_conn_node_two_missing.json b/config/reader/tests/TestFiles/not_valid_app_conn_node_two_missing.json similarity index 100% rename from ConfigReader/TestFiles/not_valid_app_conn_node_two_missing.json rename to config/reader/tests/TestFiles/not_valid_app_conn_node_two_missing.json diff --git a/ConfigReader/TestFiles/not_valid_app_conn_wrong_path_type_one.json b/config/reader/tests/TestFiles/not_valid_app_conn_wrong_path_type_one.json similarity index 100% rename from ConfigReader/TestFiles/not_valid_app_conn_wrong_path_type_one.json rename to config/reader/tests/TestFiles/not_valid_app_conn_wrong_path_type_one.json diff --git a/ConfigReader/TestFiles/not_valid_app_conn_wrong_path_type_two.json b/config/reader/tests/TestFiles/not_valid_app_conn_wrong_path_type_two.json similarity index 100% rename from ConfigReader/TestFiles/not_valid_app_conn_wrong_path_type_two.json rename to config/reader/tests/TestFiles/not_valid_app_conn_wrong_path_type_two.json diff --git a/ConfigReader/TestFiles/not_valid_network_duplicate_mixed.json b/config/reader/tests/TestFiles/not_valid_network_duplicate_mixed.json similarity index 100% rename from ConfigReader/TestFiles/not_valid_network_duplicate_mixed.json rename to config/reader/tests/TestFiles/not_valid_network_duplicate_mixed.json diff --git a/ConfigReader/TestFiles/not_valid_network_duplicate_p2p.json b/config/reader/tests/TestFiles/not_valid_network_duplicate_p2p.json similarity index 100% rename from ConfigReader/TestFiles/not_valid_network_duplicate_p2p.json rename to config/reader/tests/TestFiles/not_valid_network_duplicate_p2p.json diff --git a/ConfigReader/TestFiles/not_valid_network_duplicate_wifi.json b/config/reader/tests/TestFiles/not_valid_network_duplicate_wifi.json similarity index 100% rename from ConfigReader/TestFiles/not_valid_network_duplicate_wifi.json rename to config/reader/tests/TestFiles/not_valid_network_duplicate_wifi.json diff --git a/ConfigReader/TestFiles/not_valid_network_missing_nic_p2p.json b/config/reader/tests/TestFiles/not_valid_network_missing_nic_p2p.json similarity index 100% rename from ConfigReader/TestFiles/not_valid_network_missing_nic_p2p.json rename to config/reader/tests/TestFiles/not_valid_network_missing_nic_p2p.json diff --git a/ConfigReader/TestFiles/not_valid_network_missing_nic_wifi.json b/config/reader/tests/TestFiles/not_valid_network_missing_nic_wifi.json similarity index 100% rename from ConfigReader/TestFiles/not_valid_network_missing_nic_wifi.json rename to config/reader/tests/TestFiles/not_valid_network_missing_nic_wifi.json diff --git a/ConfigReader/TestFiles/not_valid_network_missing_node.json b/config/reader/tests/TestFiles/not_valid_network_missing_node.json similarity index 100% rename from ConfigReader/TestFiles/not_valid_network_missing_node.json rename to config/reader/tests/TestFiles/not_valid_network_missing_node.json diff --git a/ConfigReader/TestFiles/not_valid_network_wifi_no_access_point.json b/config/reader/tests/TestFiles/not_valid_network_wifi_no_access_point.json similarity index 100% rename from ConfigReader/TestFiles/not_valid_network_wifi_no_access_point.json rename to config/reader/tests/TestFiles/not_valid_network_wifi_no_access_point.json diff --git a/ConfigReader/TestFiles/not_valid_network_wifi_no_non_access_point.json b/config/reader/tests/TestFiles/not_valid_network_wifi_no_non_access_point.json similarity index 100% rename from ConfigReader/TestFiles/not_valid_network_wifi_no_non_access_point.json rename to config/reader/tests/TestFiles/not_valid_network_wifi_no_non_access_point.json diff --git a/ConfigReader/TestFiles/valid_app_conns.json b/config/reader/tests/TestFiles/valid_app_conns.json similarity index 100% rename from ConfigReader/TestFiles/valid_app_conns.json rename to config/reader/tests/TestFiles/valid_app_conns.json diff --git a/ConfigReader/TestFiles/valid_network_connections_distance_p2p.json b/config/reader/tests/TestFiles/valid_network_connections_distance_p2p.json similarity index 100% rename from ConfigReader/TestFiles/valid_network_connections_distance_p2p.json rename to config/reader/tests/TestFiles/valid_network_connections_distance_p2p.json diff --git a/ConfigReader/TestFiles/valid_network_connections_distance_wifi.json b/config/reader/tests/TestFiles/valid_network_connections_distance_wifi.json similarity index 100% rename from ConfigReader/TestFiles/valid_network_connections_distance_wifi.json rename to config/reader/tests/TestFiles/valid_network_connections_distance_wifi.json diff --git a/ConfigReader/TestFiles/valid_network_connections_mixed.json b/config/reader/tests/TestFiles/valid_network_connections_mixed.json similarity index 100% rename from ConfigReader/TestFiles/valid_network_connections_mixed.json rename to config/reader/tests/TestFiles/valid_network_connections_mixed.json diff --git a/ConfigReader/TestFiles/valid_network_connections_p2p.json b/config/reader/tests/TestFiles/valid_network_connections_p2p.json similarity index 100% rename from ConfigReader/TestFiles/valid_network_connections_p2p.json rename to config/reader/tests/TestFiles/valid_network_connections_p2p.json diff --git a/ConfigReader/TestFiles/valid_network_connections_wifi.json b/config/reader/tests/TestFiles/valid_network_connections_wifi.json similarity index 100% rename from ConfigReader/TestFiles/valid_network_connections_wifi.json rename to config/reader/tests/TestFiles/valid_network_connections_wifi.json diff --git a/ConfigReader/TestFiles/valid_nodes.json b/config/reader/tests/TestFiles/valid_nodes.json similarity index 100% rename from ConfigReader/TestFiles/valid_nodes.json rename to config/reader/tests/TestFiles/valid_nodes.json diff --git a/ConfigReader/TestFiles/wrong_type_nic.json b/config/reader/tests/TestFiles/wrong_type_nic.json similarity index 100% rename from ConfigReader/TestFiles/wrong_type_nic.json rename to config/reader/tests/TestFiles/wrong_type_nic.json From 6cd8ebc09f60570a9a0f914a002d2c6667aaba99 Mon Sep 17 00:00:00 2001 From: GrewalAS Date: Fri, 28 Aug 2020 16:31:02 -0600 Subject: [PATCH 21/22] Files moved. Config now returns nodes, network connections and app connections as json. --- NS3Mosaik/NS3MosaikSim | Bin 1942824 -> 1941840 bytes TapControl/tapcontrol/data/ieee13.json | 80 +++--------------- config/generator/ConfigGenerator.py | 11 --- config/reader/Config.py | 69 +++++++++++++++ config/reader/tests/ConfigTestCases.py | 1 + .../include/multi-client-tcp-server-helper.h | 0 .../include/multi-client-tcp-server.h | 0 .../include/tcp-client-helper.h | 0 .../include/tcp-client.h | 0 .../src/multi-client-tcp-server-helper.cc | 0 .../src/multi-client-tcp-server.cc | 0 .../src/tcp-client-helper.cc | 0 .../src/tcp-client.cc | 0 .../include/custom-udp-client-helper.h | 0 .../include/custom-udp-client.h | 0 .../include/custom-udp-server-helper.h | 0 .../include/custom-udp-server.h | 0 .../src/custom-udp-client-helper.cc | 0 .../src/custom-udp-client.cc | 0 .../src/custom-udp-server-helper.cc | 0 .../src/custom-udp-server.cc | 0 21 files changed, 83 insertions(+), 78 deletions(-) delete mode 100644 config/generator/ConfigGenerator.py rename {NS3Mosaik/tcp-server-and-client => tcp-server-and-client}/include/multi-client-tcp-server-helper.h (100%) rename {NS3Mosaik/tcp-server-and-client => tcp-server-and-client}/include/multi-client-tcp-server.h (100%) rename {NS3Mosaik/tcp-server-and-client => tcp-server-and-client}/include/tcp-client-helper.h (100%) rename {NS3Mosaik/tcp-server-and-client => tcp-server-and-client}/include/tcp-client.h (100%) rename {NS3Mosaik/tcp-server-and-client => tcp-server-and-client}/src/multi-client-tcp-server-helper.cc (100%) rename {NS3Mosaik/tcp-server-and-client => tcp-server-and-client}/src/multi-client-tcp-server.cc (100%) rename {NS3Mosaik/tcp-server-and-client => tcp-server-and-client}/src/tcp-client-helper.cc (100%) rename {NS3Mosaik/tcp-server-and-client => tcp-server-and-client}/src/tcp-client.cc (100%) rename {NS3Mosaik/udp-server-client => udp-server-client}/include/custom-udp-client-helper.h (100%) rename {NS3Mosaik/udp-server-client => udp-server-client}/include/custom-udp-client.h (100%) rename {NS3Mosaik/udp-server-client => udp-server-client}/include/custom-udp-server-helper.h (100%) rename {NS3Mosaik/udp-server-client => udp-server-client}/include/custom-udp-server.h (100%) rename {NS3Mosaik/udp-server-client => udp-server-client}/src/custom-udp-client-helper.cc (100%) rename {NS3Mosaik/udp-server-client => udp-server-client}/src/custom-udp-client.cc (100%) rename {NS3Mosaik/udp-server-client => udp-server-client}/src/custom-udp-server-helper.cc (100%) rename {NS3Mosaik/udp-server-client => udp-server-client}/src/custom-udp-server.cc (100%) diff --git a/NS3Mosaik/NS3MosaikSim b/NS3Mosaik/NS3MosaikSim index b451381148a5d8679eb242d35f6e416e7da0ada4..b3fd38d0aa249c237f8e785a59453a2905f0293f 100755 GIT binary patch delta 119529 zcmagH34Dy#_dh;&7-ETuC9)6(gV+-q5`@Io2??>sR#8i7EkUBHm}rvLbUH+z>O)&C zt(IDf(o#gDM5>mmwyKM*wmX8PYAYqb_qq4ZWTc<(|36-n=iYP9J@?$R-Q{_nvHrU` zC%&1J8(b^%zCnEAbCiXzsG#+E#7)Ry|Q|`j%FUwXHgSwnUDft@ULc znL%5`?lrQc)ECh5*BzB4@eXaJ@%uX6R`hux;!^vWJ14cuz1PWck509>o$%No7aI?fQM?W{1IHP*}(8`%jPhA(|AxHiJK3BKX@w#2tJzHRXJd?Hl2 zy$_6VQK)xPu+F%4!8aD)IDF&r?SXF}d~Nt9;G2kVe`c@?zR9Qz!gnyfL+~Aj?N*G47a97Ws{r$G zy*r}wh{%^d{4c-Cb?b{wtOSSKP3y z>o?1Hcbs_Y$3>yXUZ0XXwb_v0qYjhG5q{(5xRvJOQh@6}BzJbL2# zsb^Yuz4vg^%D=ZY_-4|Vmj)-M|6JX2?Q!v`kOAofJCE2tb^P5A>Zk1*+VJDyCng@B zR^dot_o>0{df7w&>OSzp#oyRNN54DofC+l>iBa>mt8e{S;ZdIvTg-tqI}ZI^Zq?L4Ac*4DUItvd8_{yM5v*BQtE z8I$_%JnOXTJsbs|0I)Rf5?D?Lw^}7N`A%X5revDnaa&)(C&AXp8W7r#7={5bL6Cs}f|o z3BhU#!Tu&{)AuGNjA@6br0og_W=ljb8QPlKBtp$g5aEoxBx`HHEkoezX+NMmQX3Z< z#GKTx=}s-r;M!}E)q>bo?JxXoBiiiMegL;GwKe`hrm9{A-PHDj;wkNix(s$jcAIz=_^2UPgZ7nh=$keEvXHZsQ$3L|FHG{M` z(Dv4rq1z=$RnnrL3$?^(kubz)G2BYRG-I?z<{&muVDq(sC@-cC*(_nQ--XqKv~7UD zEtJ_=yMXd^LElcaHEA^ig4kIh_jCppqVWwKN1|q3wc|TGnmeM z{cf5T2_;wrm%18*`jg1LSPh|mcqJ6Qm}s=qHG|nWp|XvFdYDl8LeXb2jZB*y9L)9- zPA}n5$X9}OYyF3_@R(s@>;)u=>0^(MOm?p}yOSPGu^tS&BpMHsjXw}WWkkZZYs;X} zfx?@0A!NQ7WVZg-IrKADjQfy~FrS*4KJYrikHYy=M2tO!S=DR z*89ReG%@xw#7WDo5zH0}?M%^TLa&vyzu+hqp#hC-Ys&LVo-ZtTOK9o`LE#Y6{48vQ zFoAP-Ajq3R!KTs(kGnJ{_hL(hufixu1OJK!n}u6^FFZ4Znwc74+LbPrESRkmUELF2 zzub%KLy=<2@YYXaz`??_vqf~;y=vJa2HIb!;XA?6C=$?SF_7EBz&(YIqlF443mFlm zNKbANkJkkxTHB9o^qHW~7DIlG)M@JM?FsV3ogBh;QNrne6R!Cq#l5ML$0<#}d$kfL z0-=lG)>l|QL$rHE4KQbr%EHw3oFm+8af(}CVEh2Q@r`DzduiI6naM1FR zOV10Ft`Ss!3qAcRGR|HxLMC*yOqlaGAweqvpGld`^oB=rc1HBoR`mW7xxDE|uLa`C zs#o=CBpI*kzx$O=^Kc@dxWmg20s6?O#G|FoDtv^e!ft96~Umo@ZTW8 z@+ILo(c~7Ubzaey3uUbrZLCsPuoY6v`=XCrp|{;)%zH%QnIZH&k@R9};uQX&M=V4Y?;IpJWA(eM-RXh7-r1M7$U*8Evg18BJ6THpNIr z5kE?Li-NO;ioWKP9S3!n@YR3IfwfokznGPv-HE=M!O&SDkk*<6*}Gw&B=2O^O}N6g zR$?WqaeKyB0(L~7c2bHJt>`ZW$ZpODOR=UZ_}&l+kEkr+z2(IaP{m+aW2oQKkbFrp z@+f@2QtZ}p9hyLT7+;0!!Q1_oAOT5u92iqE+>{> zbqQar;L(at03?N{8d8;`mU#3khi5nBs|KEq8!J7P_p0pw!>fj&BcYF*GIBiux=uxO z1a0W>8L2w1(LoAYBJ9)LV8|3`Y(e8Bqlj`|c(EJcw3-engl(v+^8ScxtH$Puq)3gm2(p_XFtrNkEInk36x`6Yt%OTgEAzBabWJXstFm6E zqJI{Nh2Y5w4t0soW_TR&Kd%ynr}u^MUeMbOtJRP^Lv0%;8{~JFsywMw`KA)I{Pc56 zsVuYH>|jK!kU;0l1^cfsiBMBp8Ze|7;OU^UM6B*9JMN_5w^cNhw^euTFX(UV|1o)d zp|rlW++_2LnuN+*BN#cTk)f6$^=WBgc)a+yAtBAKapxsGKniE*j$DRe*bQ;5rQtTq zi{YVCc$`u=MkPK!soZ2!xh7S?OBzW%MVAZeD-9%kbvf7lN!cM+@Na?x6vb#5eDr@= zdbBps8l;_X`BhNlQ|U7Xr@u6H;)KEJv!+acu1D1PxpN~U^({lf0`;->uxi`awYtf+ z$F-cxy-8%`;ECyj)5lGpFmBd_-u(xUjf@&TWzv-7$uD_<`d@>>8gBn%__?av z??2ngv^{oXfRYTNCiM$>Qh*oW9pi>SXw5#6S8= zWrkJ+l^CkihoBYk*YmG}qLx&W!rj8`>}`06zu|Zs!O(wt$P_52 zy5Uy=Fc|7gnF5dZGh9~nj8MW?HWZ^yABOTmWCvnMpK)r^niUi}S0#bea@dmL+Mro2S){gLR!~SJy7kx~ zKoOE8!?ex7(otv}iG@$H57wfc0XD`58|{Nl(fnrzh0v*|hjW?_c90eeYza7euyH=v zR@$`LL8exO)z-|e9WsczR-g6f~bi+8AJ!u>?(k%9^B?!f@Pf2|G%=0W4|U z^I5MJ%7mS#g=GYV4D-Qy7IcK|p(O$9IpL-Dp2aj_+iMGeZR^w4Gm#N?vbGsmix1Yb zBqVH4?Mz0HHg!&Qf6t1HpnWy}IYA+6A%eQW;8~Xuwx1R|C&)j^hvRvT%?Z-x&Z!>K z)d%X?g;AS^+A46I;)C@pa0wfy9Rqf(4|cJdG6>tY>9H*zwv8V4M43J?k05 zKC6Yz4GQs`%@g<33({{0J55WP8^r2wpE&n5BdfRl#=HTHwcH*%e`y6aaQiX)Rb$9Z zYN9@?f0Hd~7Mi6UdnHIa`bzcfC9fPbhP>&a!FBcTWn`LmEC*ycAj{dy*m`aAYeCwk z*Q#$n@fuov>(eUkOj)b%wr_sjY-AU-yf=PfMcQ)L)2vuK<66q@ZlAWKONAOMRG^R` zp=|q_Wn*h>-@5Dt_WA0HHLFkdhbnHlYZjN5=57zzc0R!GZ*zkOw@RC?()j-RHFx3G zh~p~X|95FAT}NbSf!{O=u9RUg6#Z^<&9|oT2kE$r;+$`_@Z=1w|2Os~GrWKTl#0Gi zbll^ka5Kr~H2qPdJ}!Z0w32T^al@zDfrj;GfyO&ItI#5eTw)F(Yz~BD2v^2r_G`BgUH0|Vp=Jh+6C6-*DANr@X)EzH5@)onS zz=PJB7jK~hrzu_ZAC^(0zWzfPtE;6Rtey0g;v9!bmnWhv1mV5@DlO%u*YW28aVr`M zTnSZ+sQSfNIpkD6Rq}o0Pvi1`?62h?Y#H1`am<9z@SpEf&-1Nw`6$g;kXq$I6+!y2 ziuOW5OQvgY7qnq3wSxt{ShiN>P#5FkG_B8}9_F`7guqR!3+iT?eyCN%^HhNj(n!)r zcOgid$5PzX8BpRpRQM;?@Mq0E;0}-0ZXN1pY?r2WFKl36+8!cfV9(t|3)n51A48j> zqq$_AlejxZ$i4y@yS;vW18;!Q+OlF#g~HF${RrC{Iw8AQC6$Y)?iWc|em4f2L3L;N z&)`b~4(3Owgoc0LD78Zed#$-Jo-O8Fx`|&P?vA3OgHM9LQ{c_M;O%@nz(t!NO@feS zX(E_@00kB0P-!CW-?`_Ky?we^%okFlMG9tD{XQ={aQ7`oZsN%b6Cp73t;tf*7y@H7 zX^An#kh`U-T5LI`8MO%E$FEG6!>n1vn|V@;t6D}6Pz%0EMJ7QIcSY$R%^l=M6W-MZ72v?QK6 zI}J6y2tBwbp+xjU%IIV4)Swp-@mUKDh73PvFKb-9qqji}UBYeymPoLoYZ7oV-Z92d zbcVFJnvB;4cEu zbvAVe`SY9k2s>5)=UY>4u3pwOTTCJ3>L=yZ_LtPL=h(o>O@C}IIZVC^$%VW*kj9x6 zyEzE*nX{XMgk&s*@!i4yqx&l~9O~Yu_mcufy(?AiCxGLO`vAo=i0!KtH7Wb!|G{Bd zc@CM1!z;wWMS1yVXUHo&FsIaZacI6;dvqkk{;Fb}Oc+3y%mmk|{;(>c7#5{&b53W+Rt2H6!kvaP?>6HWG{+jd(0bceBum&af z=LAOM0RE;x?6pRS;dQlw)fO})v;x6hT&Z(?-U^LK7`r1{}t4B+Tc8Cyk;CT z6m0}EvehLVixj;tD)uvc9o3e>S60;_UlCKo-!gREFGBS~IPwqK^=WXGhCV(ST6Ub{ zhe#Mq_Kq9;UD%!+ENcoGKq*8_5NoKJqlj$Q5gihT2tIlWHjPD}QzaO~8TPoIFdwOr z&lEGU$K!-fpAlW}wUT4X^qmMuqT?cU<&p3c-U+~>4@hzTN}M~8w8-U4W#TmjGrO;h zrI&?_?s4RBPe^}RVNB8$X{ev$(1eEi4r$>D;$4!MhPn#VsJoVI#4}Zk$!OtzL~hXk zPdoKA6|+aonT+=Q1I!CblS2gYRo?YK>_;kD_6qk~fT-ymAQN63VX_J=McZh}XLB6j zH<4)*oZT=tnX~&+k6|Ej$BC9mSBWuV4yz(K!hm;pjTtf@WC|5ug)?4E#uIyVNRoao$6o{$uC$DFeX zgFq{))9h^GjpSH3!NCTJ&CY8`*tZHs6Wzm$V#w z=QJR_I`arb4wlo1>Mqj^jsIZny<1o;F96GH-i;QR&O8H^jUw#w(y)r=Gy=d=sr=n} zQBI+9e}cPA=N@VUPc|9co&<2^O~xL9Hl|yAYoXRz*j8s$!EolJn3t!AzOg+9S z%V|{pasoo{@?-7wQ=xXs?>5Kxd==&?Hw9CI3-*Q5EPO+6gzX`Um(>@5{23+Ux?R{b zZ!&Ru4yQ7ZJ?;^hbjgbY$ejHmwU|yVrl}T@=nqr@lmWWr<$@}GA5R2D(M~&YY%IA% z1Ci+1e4g5WfE8)cJERuLI+z-ncrY3Pm`Om9P%BFS@r16bJi<)iYSS4Pnm_Zzlp-H?ffQO9DTG-8I*{iR z`Ad@gyd>Wx$tOHPZjxR^m+$<7XBC(YS+wiBl z!PmvgG*6_lE_obSbIzN{H(LLn>ek&Sk*Tujd4Zg6)Eb=$?wc!7nG$tca(($62_i-h zdD0+UqT_FjD)#}zd`7ldEnA$BEfUU^>Wg->AbUHB&6n73B{sB-A1n+;2E+%i2vT<* zl*4!bF8U+0B9Iat_Y-3tW^~{c;DzK7@8bN({Tqc8-1+!8BpCo-m2Jq&Y%!-Z#`B-C zB1o`1yW6tzRqkJVmfGJ3zyh{K>pe3-qF6iRh^EeHnK|Zyme@xKwyP#Xa9hkOA~END zg}laJB=(L%o1>5?3K58Jcu_VKzr+UP^BBhylqMz^x zrA{bybuUJd1g=U(8z4t)klvs?IskOwW064R$PfQeZhk=+$Jde3^-;pY&4WId*i_k; zJQ>(ke`tw61qWtHT&Bd4E1PppXqGb}fkP!`wZxFiVj|S~p9u+WE;0EML+)zMSq$ZC znP=+O`A6#KyhQE-GGnqnji0M zUn-FoyQfoWK1x_}mUEBiso^*x5;H>3X;NK|y)04^V$Nms;i*`yc&vI`Ox{m=w*?%? zyHEc@?WK2jQQlp%B7ChO7$o?{&duMRh@IsS%s_f@tT96G38mtE1G`K4~fmq4ctJX6;=_KKGKOWg`j|5mC;au!st zjhqoPWskXD#(^N9G!y!emS@hq)skSVm*C>B+WsHww4*)_OOkv^azc`1%u{*I$3m+w zYXeW$wr7kgOL<$NcF0Q8IG-)~2wS^yEU=Xv?cP~i}4kjV2AN#S75Sp%dDiIZ~S@?=Ql z34c@5s5c~N-RJ(~HmOghyJT?Ti+%!h$sL(JCSVNsQLa=V3JSmp6CLBvkn+UMn0Z3^Kryw ze}ewY|A++o7X^J@0J=BC5~@a;N=h+HiM?Yf#jaBxtK30}A4U3h7okM0zix&GXHl_31~JpUk2e_Hy~#(M zc|NX!LG1Wh05ksqlU=x>;$Ekiyi82qQI#dw;Jckt1i^3&u;4|>gvUcz>NY{b#F*RA z07j2RbB_qEiQh~$J~N?zmHeKRr>T!TEl8eVCBh%W(IiXFW8YI{&LeHZ`B3}WpU{cp zjM#5r&q61HM+B&t9{{u5uLH=)s893{IA3iJjP2i9_UdicOq6lvwejR{hV$_H+UD9AL;}v{WC4vsDx$ zq@jIid%|KSYl-gYJm^hDBQ~_?c?}N$MG-a&pihjshbE<@eGK5IUTHQ3^`)qjY?Z|{D34)C{xlPi zvrlS~7emd%htT4XwxKwD8u^np@?wk54F#XBR{nNP*bGP;|AR`9y&^>6r7&sHN;kH#DdGTy_mTA|0FK*An*jxxMj3W zVm_w}4g=2%sHBi(lU-6|7Hi8cH`boH)4$bCj3UbZ$M@xg?g}dY z>QVezgbCPPu#pmv2n@Qbu^HqPfFFxqyx_MLc*&Dsy8^%XBzUp{r=BRa3u7Vbi1|PT zPk55NvjVq&65K?A>pcmsuD}(a1m8I>1-}8b&v>ewRq#{Vu`5jmevTRiTRx?*k1-wNt=W&F9 zKSc|bE?8}I_1=oDK*q+Ry}2~VTyUes$$F?n+*Ucm7XaitSw8xXSQPU+f>kje1ANgD z;Q?_lsno-1B7&hT%E+|LIQSinAHeg0>b%xLIzPTwlyJ_D@oyF7vQ$Q1-Wq*+!i7>>ebk9V9Wmy6d_LL~Y2$AO*-N0Hq7}5r z8b+{Jsg#J4`z0aQJ>H!vQ&FL@kzdMn=q|KNa@+p3Px7w zPB3)XNsZ|P)$TlKq-X0Gi+q(E8yc4gB-cPRu4k?v_Z7UL>Zto0^O-(ms}()j$p=00%Vb(00P-XUwcjuL`%#Z zaZp5cNQpa8yA+6~wSQnNawaAvPBFw8cyE%}`7%~=2pG`(3>wnkF*Hxex^79(J}IeH z`ExRJ-ediT*{pUox)shu$$nfvwh%WM@ zt&wZLHsG(o$V$W+)=Cx;AfMnthsDZ35elqUIj0Yl>NEeWSI53z;Y(CroQpP_73_q9 zr2)25z$ny~s>HKZVJ8Fovcif71|AF5U<2@TK8Zx@uOq5toH)AkhV8Rcpkt-2T3Nwll;4I~hRFN` z$8DQyDsDKsM$@gws1b=!0cETNXS$Wtm5FwI6iqJ3IN&CY|wh&X>9y>zc%GgeLEb}okB^;6+5*b1TBPs zy!}48oW&7^I|_>)bzI>NMY&8xB43ed;3s0Og8~0gG!`ypm$=om?Q_Ncia8N3 z^(NH{O*$_0;m?-2-~dUVEa^X$^gSf~(;oW3_9UjuR6$S$)<+vSoc8tIK>H<(f+HY5)Y2RvvLLybumvIX)r|MfuKJz^wn@Ko8u-AC;x&sSbT1NTcIx- z-9Z;Ozs31|O#-@SIm?x2=fP|RzP7e&9M72WGAYACf$DozUC4D7*HA%l#(m#@h zH+tyXfF8EnC+!}DCWWTW$}5EJ?5^0pG+7jyKJb7YCgFSz(;CU_eTCo`go;h=Q7<%w zd&pgZ`{`_>(A2;S5k66y9uIPu>HvyMAYBSgwLCNwGRweE8}LuiusL0TborNdrc3Pl z2c@N@f$hQcb}p(@h`Y=5EL~#mrw8Ip2$2>Ph@SGB$W z)HANSqW$_$Sj#bR3qwY$p?Ey%6*PuKm(#JOiamr1KfDvBn1D_XnWEg9N zVCL!_A@7{DmJmoHpVDd0LkW^qFxeJUl(9d-*&2^?+(@^Kf*ZqC-2ZCZ9@vcAcWVzH z46r}D8>BhEXI!LAF>1^K1`WnYM#Bj4*Ipp#xpTk=$OhdA{wv`7 zYSLWqifu!H#b4_`%wR$KmRrUu%`Nffed*So6sfH!p&;vjgy7ruw2<(Yo7Dj$tJF0hI}0o-a&g`sX4*nys{LeH3~}-lf?m zD1I--X5bYmB|!T5Uu$oc+So5hX|nyf{4Q%#gCG+r_R!s#JUx=J4o1H(^+}AiGyd|0t}_;4{P+v~ zFs_Lgz?c$ag}L1Mq9yA%uebZ%sA!%*^=kUtMsNpv->O;~8;_dR-t3an317JTJD=9|7#&#l1vSN)89 z0>sVs=)3}p9Nt}Y7IqGuorc*x=At{1UeOyuA5!!?XQ``i_-67DC2w2F;y0l9a$?~$ z9Y3q5RfN3=R74g;hvRqa8!NIF#ucCIrz*l;&wZ{}Ho;y|pX)KWjynU+Pugq$XE4L} z(q3N>+H0?MR4cRB3L>oc2&Q^}EB++l&l3xf!H&QAQ#v2DCDzoxka~>z>=;@t+N+o>C{tYBO$so=yydSQPLm1C2f*yk!JUQ_= zQNy=!|EeyCJlSE702g!P=lZ{XtiFGNkZsZtw2s-WH?6{&*oXLV8Cu3=)i!X!GM&aU zh%AoO=K##+9Aceo!zwq8ATJV?O3T4zjZ+D%+@*#RArY`dTHDgzv6wiy(ydloKSwcE zz*fGHq*k21kMRyB$cK{z)5@mD}{D)mZEHFMu#UtAO>2nQE@cvyX?@jsz!jHmpiPkDn+d4W&)&7JxtfA*5`>SucM z8f=Pj>PG#|8myD?@2&cg8Z4yFeZhNSpygZ2Zl&hBfepUZ@7G`rf)BwWv0e1wTQF+G&cU*l-56FVHucSy*#KCQ%SeUYWd=Hg<53$djCJ zqACt@c#ZXXiJ5h_3?ddTQ#CY-JREt~(@?Beou)Sq>U{%P%ix1xSt#%Fp7tmp^IroA-eu|TKiKGlnBu}0?oO7IEzITGG|tKP6SYi%62 zUQepcx{MpLmfUcmX+DMr9p&sLi~Yy^(}68-{!p|;iwzg}$<74~pHtBWhu%ynTpl^3T*@*g4{W=sNN9fg=_KDOEd<9wODj)ob{%##+F|v(% zUL6)`Z%d-bPW~Rls{qp7wWP%gBs`hmMIV=?!tN3tP4FKHuGYG(B-}#qJp{+WFj?N* zPVo05_(ud+OI;@EOM;IB;RIq|6Poc|vF8ZTc|D%gI%BM>zZ=K`>R*77D07U!m0yD9 z`1j<6NcZd3=!Jo-nSJbP0N=TaKPD;})|I7)IH=TG%b& zY9839x+ z*@)7}laY5x-bs$Ptn}kcHfPw!U+F&tv;I}ukW0Bt(|76NA*>nOqYnsS!>b&Uvc2|& zz9odMHIE<d%Ic(?z|StLYXmmrCzB%n^$G@yMmSf7rLW9YdrLG z>FA!DjC88sfGEHx96h$*RfgxwA%%R!HSEnVD2&u8y6p44iuuqR+I0Ks?Jzv@SMU+B z@i|n-1FMuuH@~AthB0fcpcTO9ogfjT!>?X?jG;dPlU11P&EQ!e;)($-#*kUHek`lh?RP` z25hr&;5+(_2AFz3TcrmyWUY)ptkPo}vT?P#K~DEONNi$HQIRisOW)d%S?q5C{5rsh zpn**gL7Uz~96a}SS%6Li6vzok`n(jfdjj_-2~Q;WRT>k##}yk()%zcS42P3w7qy+p z{toq`(!fm#ze?~|2(Hq=`Nl%3?+N}q;QPV_ zpV)l_2w4Sj5ckV~;MZ5;&o9D?m@(YFkm-2za&Qto+g(wwN>(}4(n4LNNRjGTMHkZu z?gu!e94ARf5-53Q3n`91a(R8mI@Ap`Atj)rdF!2$>^&&mC-{Q(Wy67MHvSh9u$n|Ya?Dk zC<)R)x#DnHzt)_!G^Q-o>xQ$mDtD!Jw`|szhO@c>pOW3>T#Rvk^{M_vIP4B6@w_j` zgVO+M_r6HE7?*RsUabY@#*KRW7Ho8tvts5jeekiaw_xkc(_t@CaWu`1Y`LD)lFc-p zeN)eG$@Un>y`e8?#pW18mhHULidALC*f(_6hSfKIuvBl@hFOjOIAwj*Qhj_I*4FsK za$Re~`WP#`uKy0YDwiEXgttF>yDe+neT`I)=iv&vhq{gkgnl7|jg&`NZXq9annKp1 zg%Hl^AGlT@*A}zZx^ja>lgZR1;Z1#cTNY)k<(|<1f!yqMJ-8i2&2;JA z+Og+Zw*F~5*3`c6Rgx@rcx|Ma&)=YOw*18dS8PwfY>tXn{tn>WBnjIRp@Rq^Pn>+D z;To#D>p<(s<0q(*E4I@PN?WfJ8Es6Ewg9j>lf_nTH^DJ+xuSO3iQSQ<)Nkx&Dxb^t zWSK&DH<-w?jO*u9_J^-Xc%l1MWH}E_n3v{&+usX6;9lwjU*d%qy2DqNj`cPU@e&od zcY28qxS#WZAM=5~<%J(`|L6nn<1H7sSL=GKNY=x+G+Un$3ID0A=~p9hzV-8)I)3nI zrty{6^*7qHZpJ~c=ttYLX2xsT`tA1Y)7oR<4SeJ)Wg{E(w!XCkTi#$NG{>KHVU^{; z8_>PTTd~oT`>QUw`uL|P_t3{i^fc~HCsR1 zkwpa6fW7DzXeu50Sj17wIes`xZ`ujIHhZz&uM-P5CgkWDomlHy^%i4FqI=M4%U5l& zzP%G0XgqD#D@C(bfkhayU`98&95*RxuYX1F6OBdJ(AV@S(ahGU+G}7@^Is1OT0drz z=cxxZs@wIG(JZF@U-Qe9*LGQ1xus9Jk59StGCeki)wAQLi^Yk&qq5Cux8cFl6nTeZ z>Ozvtl=Chr_hqQP!YDU~l{_=5a6y-871|HAIUd zJF^N#W8F;sephTDE6&{+8q1=Y@%5MVA>Ei(sS@nH|0VrKH#Xn+(E|O2?rfg1Q^wA# z-PuHD%$=k6k7t?2ZZGR6;@QGV6+k?4jy|LZYu0fVL=&g<8U8dM4ZaV*n{EdX&fv#; zW#FlTVik7$E{zRDZRhA)dobNt@RFX;6D~6IC4E&-7H{k}bLaV<>_cW8IZMy(&GHlR zPzaxZ9{83y9?KN+p40IlPtK)uf7%hxnF;K&muWXa?{%mD%_jg-bluZsU7)DT{Q)C2~c6yY`seYYi$1qUACG{^7q2_C+39B+~dLNUuSM(flb0$_LCP*>EcX53>ZM zm+*!F7P&p*{qUj`uL{_})w2!y9|>%=F?W`}urC{8>^w{VsW01Q+&WEP(vO8018461 zv>&_2j9s7CKTKjf>feS4?Wvnp&k32T-2)*0c>vy+uFvYvBH||kj*}hSe=EvJ;E5O+ zzY2|dU#AY8LK2+gCy5Y-3^1gd$#wzU01U4;Tff+!H4gk`GNBJxir(dKkjbIagH!a- z0c^4H`Dyyv0c>)e0C0d^5=n9P28mca?|V+SB(vtmjH!A;GHX`p4up%DtY;)6sWh0O zpGam;8>61z88VR7VaBhg>Fov~#o4FnGX}9m#($^kw+6ADQ5p&6s6f+zlWw{6#F;O} zJbwU@5}i2pb#^KG2=*9R4EA3D$Su$6X9u%3#(~f3{zKSkc7lyFVfKD_BV&ZI7 zw1Q6=w{!UrW@N_8&*>|NvUFp+@w#~!t6yQ+q*A>>g0UeRtM?zqo@T-N+r!ukmfE>k zPsg;Wh>JPJ8`b1CikDeLvCJ zX3tV22Ta3T5zlxp<8*?n_X^zHT?;UZTqcrdQi*=SEg(D3TtQ|{%mP!PJYJr-K~hDE9#f) z^pII>G8pq}z}cLGF@cNCD1q*e!@RG~|F_-*siP3{62Aa2C?Vu*NL|c-@FB}BBik*> zY#@sxvJK;!lx=~IJo2*B1l{aZqPaRje{lqhta(XzPaz+TE5Kog0PU2$hD%aJMeT*j|7Q zu<}}qGH$}GTCA@b$y)V9O}Gaa{(v`|$yazw*ukT+_pg;P>OqViLH{sLjW@ukRaB`{ zH;-Z=Rf(;6O9`JkT5ms!MRjdTmi6#kFFS&bQ_7n%O zw1uP2kBrhk8ifFJj?yoVVu?mqsvbF-r8GY<0wFUUe@AzQWqx`cxb!V^O=J?@;Te777#3}x0xsMNW#fs3 zEGS>pccefYuGl2P`Jp%Q%TWC0a49$)1I|UVo|H?&h#xL*+9f!S4o!3v3|9B-lALhx z1vu$Kj&{9gT}=+{NXNN0CH%4*dUnLCyrY-s$hSG(6Kmf@c0avJ5}iCf1Mg0Bz>gBL zO3miidSf$)5`K?pHuf*^<}cw5J4BPk>Q;i|G#z@a5aEMUYeaF6LlvXZHLanZ*+^=V z&m+pGxBj(bq)C`ZlAIIhSWfki_vP7n5&`dUzbiz*@kBz_zYw8`5aC~lum<}!h)~(L z>$RfmM5KUl*|i1Ym+~tc%6FWNe(79ba0KO*%A?6g>0l5KLU82UIq*P?Kj$;CgQL_s z#2WBb`b5$O@{$tMwVob)#Ey%!J80sx83<7vo$A-evC!^g!Q#omK7##h&J3tvC{Did zCW2&RW4CzYzscYTPjMoClb;->zd4q*vfrU38)t5jXpKmSxtUR`sExT{COU%^3j7jd zZls5a7vQi$xG8=Ug!91&H-*f&i0A9lsVhE4bUhWfEbu!t$!M5iE^0?%^ndcHMttnD zmyC;|SrQ&$0k>ivAh=08(t{Ie(wP4Yqw%%2(ru|LptCJ1NP+%%qoL3>t!9h)DV2uO zeAd|Sz?BeAtzM;Y!cRic&NwT!UpAtqpRKT$HI2qAJHG#n;6x@{MV)2EHYGBNe0d~w zKN@=ij8QBM0*j)`p4!v5;;x#p$us(qR2E_n7qZe3ZrNi0Utw%|maGhRU%+IHc%S() z=iDRkqJ!T;vQc=TCw@%)Gx1|Rj~S8M=DbJ4Ks2cMaKDZvyRscTt)FnUcP_)#wusm_ z=WGx?;gN@OUPdP_YtfHzL7V9WJnm4o^%GKxoP_nru`Hx7A0kF1jUw&Q9(w;j{B3v% zxj$KsZZHX_E9SGHUFc3vdX_b@CXm74dvu_XNuA+iZZU)udn}_S`C*(v&wUohhw~6T zc>D$K2v!+?(t}Qjf(Lb1p$E(6)OtW(lQbF+7j@$tCe95kdiu$P>sR zk*$sc^}lIL9#^8aM_Cyv7S zV8ITV%;sVD8QA3_(I0*Vi9Q?i66M^L@D#ub2o^9%ls~2Ngi#pv{4zJ<6$mie4v5-L z{*4H5KPanTr21pY?&-7ewGR=v+ur8hv#m{m8Am{W0?jkHDJo7s( z-aX}d-ZBm>d}u;_;0Ju*6Mf(fyyXIS2XFa+`__cgPTmeGdl3chSHUQ^Ecuk5sBMlr z`ri{+3p*`KnR)49Qh{e`z_KPS(Y48%iIEA9r8vbTG2}XFLbx&JAhG`T;{!gTmYAXC z(zzrVH1xP37O$lLMFryE5#e|R-a=E_mz0>K^Y^mqDN|T=`&7)9V%1EKca-wGur5tT zn7tqKm75_1_{*%C5L28{yQqU_*N-P0{Qyc26E6$<%tAfMj1r0G8bv<#qy?Lh&^Pni z&DquAkK!KTV4AKH9T+inYN27L6w!|1DQg1eU`)`MzvOuf-J_;^`yhz|36dDLPb7bH zk{_*;Wg0v^KvtE84y$TemY-qHUWK&;H3_EFUx`vudK-#TTFCgM{hdU%=-_%lpGf<0 z20j>}g&$_!T^l$k|D|)n$@AvHr{_`-qiWlP?X|-AR+Gg6xDJ+vk3`9?R;qV zUp25)Z#&o+Y+p`dXD*}>yarAf!JM8%@BnNmhG)?=EB3dS)f8RIBOsyYpmeNE8w*}S z$I+CMRC*XK;S&jN5j_vZo(roc+(jf^}XuSZK=P|GP zWu)H$EWC-_iX{HZhwc%jCpqvB1xvBzBPxxk5U8Y{7q5kmF<`St_HczGf- z5s^uYf@q4Ah{Tu&88wQcFe4^p6=E)akdA=qPVTH`Sev7cl~6ogOs93M)Z!1(77G?y zLgDwl63KGKJpOxJvCp+*zx$tfTz>WcHy&q!q%0n93oCl#F_1ce$SNKysVc>zIlCuj zD{=Ii6N8eSA07-9wL_8C8@83Udynxho7*bqeu&0X`jIr15LgY4VJ;E3hMjR(rJOKl zj|3TLN>7;gmAI2cn@re-k}9{zcCvvh@WN3NO0|o}Y$Dp(so_(odDaxr4ev`G_BME0 zuJ>(O7m~tNWRF!)Q8RM|8pgE;-umAN1osFZ%g4^70Bj9S(Gq}u?hgJw%}&5w38FHP z%GHTaHDLKI8~(%s#iQ}ZGZ}Y0CDKmRi=aJ`1h|^d-~Ua(!w9|$aJX7cNm`Xa1r(QR zN$}`rL3(Qr;C2`BQ1kiB(*p4uAu=FX(J9pc8tG$NcRV916E&Mibuhak8O8qD8A zzu3d}a#{*06wvuOIuuZG0kj(1L1U|^=X=Gri!^{_|p{|c)&2r{EDey3;j=sG;60&zPZO! z;T>W_UCfvFfdE;tE~1dgi-=G!VB0+Dt4a=ve~Ib@+eU}@7riR@?v}@ zR&h8>62CckO_})4^pe$W4XD^C$`u&q|Z~P!M z`Jp~B4YQQzMlQV-ycb+;&L>~%U$0>K;7&KH=ozZF1Pl%u@0?~3PxO!@ID_L0dy^0t z%sHO=GgUJzz3^53i~HkdD%j+TjtUG z;r6}LmD}6QJ$FCs4(HDi4?(+PTLZ(d!qgO-nKF}y6Kr-*2yJz3>?M9) zt7qSZLzTUtvmUWUX_;n0@$@v-4ZFkf3qF*e-Z&|wh@vh_5SA3FHpq)nN6waON(bC7 zGqy2C0tHg`az-^k1>;3GYDsx#I@$;H6%J^>jt0sBvzI*~N;M@)7R5_eY*89`nzL!r zrG8^EHg|JWyju=*=U3)0;bs1U-=89%>Vi`)b9Nl{=S(tW{R4j)Um2T3;V}Dz!;rt+ zGQXAtnw-P<&190<*+!dI&(O;iSBGvPyl2f6y6_+MW2j+w0F~)U*IP0}iFAcCqSc~{vb42T z)N$N`6m$~h_MRk%WJ+o2M_eFNy1WA}lG|!Pkh`d5#}4fysR3)+Ldw^9j}(UhDjb%72ZM2Phe5J>(~=K*_s*AeV>2VGw#V6dB^k znevu+8$`ljWQk2clYa($I7OykwG zN71)#{#Vh@#Qj&%eFcmZjl@U^G)56+Dr?ZsFEkY}UuD~!|F^ceFin}Z7eR$yZFffH zzuL9}O4<&Cdns)XI8ml;sqEB0NZDfd>99+`Zv`T+w&Q^p+TPtU%H#ZWdPzDK3a3c$ zOwG~?W!jGT-wrOd?NN4AgvYJz(yu+*e(lD8wf%Ru|7!c3fca?qxFYh^_HF_5)%Jgt zZHI6B!MEf10%04}ly5)AI>oE)ov8d*+iL(NZU2cGMrr%f@$%Zf^IMs=rLyxu<59L< z{FtuLHZA>vWvVIjZKztgafC2_I zYkGGk%Hp<+5B^2KuxwcQ0;ba;J>;@tyd7fza5(|bcNXQBsQgqfXsQp8{CNp|^(f9w z`^N|hJC%FL@@y)3Y$w_MvcM6-AK3Gy!T*Eks+Mozi#lksg;Xt56TEoCb~9SRD-8*%7!~6 z#R-n-C!h>* z(@;il^l)ZE%=PrvDu(IjCFSe#=IotFLp+rFz<+F!i2rN>{|gf}2q_!MBe)CxM}`#1 zELlH0k44yWV99@K>CrLQ%3w+cTKrH2dKmkVBL+Y-VS*-rud=?mZ8Kj=>E_8yZ=x(ik zdpTHulSbS&=L>j$ z4JQi!qNVyF0lM$#t_~`3ItKO_r8(!oBjkWkBpRh@aDd`7))nm)4@#04g6<(m+{hP- zPU`TAIfq_ZbJswGl`%kr>*gFMA=Y>qdmHTe7jSwr&fB5vKqL4czHs~(JmAxc;Jv+Y z-ijuGeD7%(uSfM-SIP*g5n$3o{j?pgzkT!oTESz3x$xUD?#sGgCX2Gm-&Dn{M^7sR z^E5IbZk5c%DJE{_iJfsT{I^9Z9RSDK<6M4R#2A%^bSD@d>dCfdLbY@lAWmbPl}eMb z*9H^kTuZCD^?4Uh6C6Qe>*XA7X*Ik)&!MjLy_w8nS=}B*Ot7>Vq+hwsx{n7IHe&0I z5*}FiNB=jIO$giOPp-07Qi*38=79uHH-O}{zF-lH3VU9h-eg;&$pM{jh##+`^`W0R zdq8#l`$c#NtXp;c@gju4aq5%qT<{4rHrFP>*CPd;0n~@`;vtRG^!Ye?e5cJvxFq3_ z9LGB5qUO2ue*ie+0#Hpi_v(^rnR63W+z83f_$vvMd!^o8p0muJ{B<}6Mam7}PWW;! zN2-O^boKz7E7<}Tg>hC8AdF&T!JhN)Xi__fcY@8?YiTrKS0y3lXLHU%)V{{JK1`|M@JC& zUs}j`;YoV8EEa4pKu1sN`8Pk0p6}E4(EMd3JUb!|FJR?xqP-8+cqD@1p%shJJoS|j zbIkl&4;lnIvY;b8YC|1GB(=Csibf^?tz1|2cRdwuW8dQ0mErW;MlJs%!#b}Ft}+>j zDR~+mMpACFdj^G2(8Fv+15^=&`S+dvPJ{ zZiPC`**BrAB;5N8usPqd(jpG1cIP??`2cXyf6Y!r@bt>01y z7->GPVh+gD4}BVdHxBlZ=9xkV2Bg_`+~19fOKd2!EC%UOOE0)^`%hqM8z4U2N9~6 z7wHY6!*F#Pahhg2TGPHo)sjW)Y|sBV2)gA86F?ZWrJv~E z)&ZOYrq$H8@WD2%;Y(h!0INbm#!T|j>))3gn(f#BEsu^5YFf{A_$3}u5Y+4%JHv}RKB8n2VY*7+sT2$N-shJL*T;qoxt;NF(Wfo!mhv=ej@NKS!%w z@k4|+W0Qbb&HtLCg<8Ir6B4Ol!^1f2{8s}|fApAa?-kmHP@&}T?26$Bh5tYav=<+{pS=zQ#KjrEb7a=2hQ&+e7Jo&r3{71>( z`zgQtdYPJhu3c+B;JbT>Ju|G-)-^aLqGxclX+eQ}TtlUZ3cU}?`!vWxe_v)aoiZv7 zT9rtg_}3h#ytmf}+4(2jd#+Z;G6RDGWc-iq7}#e(B5SP)X0CqQjp&@4Tkpj4=V^PjraUcE zdx!09#Q)CJUTZLnOdj)6UQ`yUz|QfV9YWPJ+RR{@Tp!CP&)0ghTMhZa`B($}n1?OE zak<%b_@D*ac5OBHUZ@Sw;`!?fwRTlwYr`7OK0}o1*jhMWzYvEoyR7Ax7HTK!R-|bG zXe*I!W%U%F)m6%ircG-xVh;a#k(R<9G~njNT02$}#8Ve*FZyS) zkK~$vm30x+(1o`|Vq$10uew63&X;n{yIjF_SbKfGiDTEFoTEXOasm)3ZCWc9DO748 zA@`lpKch`Rr|iexs#DgVnuxTh8)yl!=Iz`VO|s!siYTIoqEir@X;FuXN^Qgq2&Sm_ zBvV}$xd;7XK47U97|?PDfzu?|o&=3=A}1znlKAYUTEF0hi$NbzG`W^hLCdFtg2k}~ z1ip|`%$FtNC};Hsaziyv6U8pm+OpjGeCjfs=_!9$m81KPxpu%H2#Vo!h;id`M{--^v@C>2}t z)HWh>ZFYusi$yDbaXC()-U{aZKGOo(9X~$dGcAhE59XWUk6YxY5_75h6N11zC+Im7-e?20#~-H@QT68Of1vSmOu{~V-OW=I z&8h=&!VO;83D4DC?mT^u8;#xR&eiX`xgWITqgH7X;(D(oEnrf~9Jx1y6lF?J!fcP( z-V=it>?5R8v2ADw`b8E9(=ccVreVKVye%t%%3fsF5PVGOH+jJ4TBA?H8FQSe$0@q@Ef6<4 zP$l+$Ey};5fH`N(B+i=L_%)pF*8k33E3 zC6wasQuSvkLt6u9y-jLC8`p+PHHLRm55Z&1rU^M_4Yw7J&xx~+#73fAiY8vF6oow* zo1IPRpVJJA+sM|hsJ@aGE*YcwYwIZ737i`YnK#DV5dzR`huJ>W2b0rY7PB=n9$Q|X z)8s=8e4kgwUK9gT#^kTi8K1mC{|SCM$xG%!0*ZHtr9L&f(ug9mq*yYFASnGjq<}Gl z?8?uU(Ld5-LFza_BoR}9pkosYfH1}i)cX6$jukrZJ^A!6w1%zL$huA$8jWtqAobr+ zy(o?-0IKxXfFjI4)%Y)8;QEZdF9agAeiMOE+c^4_*t}}C?@R!OTF_2kQcmJA(1&n| z++n>a>ZBtqa$=@3%xvpNW~?YsmSVp_Fnjk9GdcnWWor>_8HMnMDXM+o7k$Xw=#UqB z>OOI{9mz-{&USz*QW5qE+!3<~gdNi~>xCGx(L6kF4K-jg{b2DF6%2NYjP8OOo~r#w zxpM^j3usT9DxfyH6e_YyU=K`u;o;Y-SWPLa=EyOfa`PjF4x~HKL(SIT;vz1h5S^hy zR8_uFPv=uIVEdRatsB?mB5!pA^8(r3t#>kVrffm?oT9+J>3^ndLOO>!<7llFF99I+ zIC?B#8HVV6Y#)STEd={-jpAuae*@q+3|Od))|8Q(()$8NUA{4DRQ~~@Qn|2RjX410 zNd@Pa-zcg+#$+)R=43xXvL7FDk2d+5dYpWo{p@Oz{Q$7vC!%CpO*1-Hr4}lFaS{2` zcdNX7PY**l@{)zQ;D=E%FLdsRvV&trru0fuzVBFQ{lcxff%4v$d5Kpk;Z*h?<|ev% z#$!szQVR~sfN9P#LE@B@fj( zb$V<`(8^8pEgh96nuKITR4m?65m7GU|0@@p5nScsOSoiNhhhG@k{ZtS$*8L-65;11 zyAT=s%Psi|n^y6#6)gr(+aSvYp6Eg4EcY+Tj^cIUi4sE9?@}V6c~5-hi|V@}8t37w ziQWi>nZEX!Mm0lq1Il~2WmSMjchion*;IVuHYlu_%4rfNG%S zIK7Pnt#m;vwh(r={w+@UVwMg|E)G`AV2M~kLQ$@K_v;L6!(v_Zv3+&1+=CF{T}-$&Qo698^SzEb0F;;_*%+o?sYp zif>T|*ZD9A1P7^bocG0pR0Bw%gtTBm8O!^sY&a!0umaisby0hc(i`a&t(__TPwM=) z2UfPzhA7abLC++W`j~$DMF`Q20cFFK1#H8$&yhtCTVnWUvU|R{J&q62^lK)hBBJq& zX@0#Nr0i(g@GK|l_q2R3R3VdVxgYMF{HFm<(Vf){*2Xd#U^t^Ul4F|gh;$snJH&t@ ziQNGxbMjR4WZaCO$8(lxUKVHeO&Mtve5MQ@jbX7gC{soo^kn2w4`WOtJDM#~_@C=& zK8AFtE%XIK_DL|1lDz_|B07luO8{Q^_j6qpYUFLfvX~iN52IA0K%sb6M&AXeR{7bD z*c%yV+fJo8&bCCBVxZ4_f!hmAJGRKmauwE9{mf4D_!qeb&(-)fN-S*;bMQT0rJ`EsicEITdLfQ+$zPesdAHH``j zKEdjfpgxJ}lZ+3UUTg6eX&bh^8nMOOzs!<|VlkbJNSXFkMo!EYep#qtv#}WMLPbym zXy0=OfyA>a$YRxQHs=(7@8 zwlI53PrKgqAWl422J-z|wcwy!@}m6iktImYd#DF7H+b+TTd`{Lc}a<({Cs^_pu-UI z^^t~~ENz6Fdz71d)Bg{5Opwdyy1UU+JegxmWoa>uul`O8h+K+cwAmJm@!GyADA;Ce zwpo5MavqTgVuQ`r#nBRC_fv=jAaG?%MiRgO9gezq0V+7oS~*rsB{&|1Nb-$dhOvq&ZT^k5NMH4j0QgDm3W(-x6Rg?)*{)O zZP|p18C;r8;w#Pec+69>(TZ(&Lgi^6#YL*5Puk%`Sj;1ksU3)C@Bki2Bs=zu){?7? zJ5KZtg(l8X65|4>bC!`vKA0UcCYGRQgYeNRi3Am1sPN@chCe_A3;SKDS#N|QOjLx) zitw^Cq0ayEe!DfldLfD|Rgq;XvU5%{&wqI;$Sg&qB-_5#iY!Z!6*|d|VauV}rWi&3 z6~BeV?{_L-jtW?)0v>S&T<8i2D@7(fVB%t$3UpZox>Hixlu$dJp+>qwfhj5rKvUrm z-OKYnJG9!Y;Zr_-hZbn@QZY$$UO{CO1u&$n%nJp>dy!=ErJ_()t@~1?+{2&DM7#bI zI*W*1n)OzNmddw>pC|Mdg_b6~K%vPPU_g5bJx`)L?n^?9Vv@pVD*Q^qC#&GnL|;+p zr3yWr(EXP1=$)|nW(q~+05K0FR478C{_ufx(N#nJ5lTrgMYvuOHYdW;#S|#xveX9E zTdj%kSJ@`)o1zHI5aAgjwCy9CMk1GI1C$F;%;0!_a;Mf@>#$^(*6yVW$}~MlDP+}n z_!t3Ta?y`nCLOu&jsi9VaN*sPHT|o~4w*7oJbwASvRmgJ+x#|(ugy!d;u8^x0vQQx>QoOMKS_2g}M`6j{h|x#V=4&-l z$jb`3Qz5H9QkMQu2~yU>k^3?sGK9SH&}rXpW_k>yWIWrbp@jTM(Dv|)X^`L6g%Tu< zXR$&X#&dws3lv%!&-)5(7>{K&;U_7)G@iiUz%bA|L#R;WYwK8eU~(=+R2cLTUNoeZ%lBXp)CSg*6QC$bDsa zTNE-?Aq~S@c3&BuMIl!!q+xh(Q@mt&2@0E|ut!v?k@uD1)ltEfL}w#}uJ1m=Q_VAK(++d4A|5L4AHgr|w+ zh@+Du&{J3nDHoZ>Wb)Mgs5I;T%Rk?*`LTxo@Ll_{1bp%-FWQev^o&%%$|)eW#bOAb zoq%jvWv>_AW$LAhToe$;e!;*D*n>UFqb{xRNfj-eLj2giCsJUp)d6M=VQ9Z~E?zXo z#$pRefIeD%*z3~_vxpW+Hy(At}Ba1b{ckvCwZNgM7!CTFPe{%rm zxrsMXpUSH}?FgcyX%E?#GZUhMEXdh8aD#OLym$ac3evpL>8C%Gp&{vH<)xywDjU*T z?cu!u6&;l+lC^@cCxITKZ)dYpvt?VH^`w*!Kd+evY(ShbJI`Q!3PXF)~ z29N1(O`|~#dY|9>knqMyA!SF)Sf@sdVao3({qhilFhAg5QViT|Vfb*3hgGaQNL4n!LeW_Z`gYr(8xO-5N$g62UBtr|1Mc z%GUEn*H{8GNZ+`ihUXsCUT&})XUxpI+o(Ua)b>g{fKcu)!S>O*MDy@NTHUgg3m#Ue z1-xdCu$$pArH`Pn%GjW8=X#X1zJhL8lff9On;(5_{rt=Ym~jMsK{p@c8!W%J7$0*p zE#4k-NUm^guF8KtgnKUiZ*k9DZKD>>vvRd&jVs`m8}aY$|H(Az$C>HhZ*z87Yw05= zHTDfLgxUF39(`DQw^1_{I+)~j1@c--cw1|E@k>t(GiWbH`P=;LVXZE^c8fnctaT0i z;ufVyM_e%X*~iw>d83~779W_W)vGlI1pg!Fez&+iPiz0Gw8kb!X=&l$qcYfndk7Ql zru5v_B=Ujk&r_~$&U{IUyyo9h_Tyxf3myz|E}|AXA#2x2Q4J{0F}k%GQ@vqa)!=F{DAwq zN9sHk-{AjMnsH?aDmBx*kxlr)AGFY3pSOg;*f-Er8x9xH)MOZyNSaa(J0G`y(?<0d z7lHX`QwEXggCWJ0EdHYxu^gjs$w4yiOF-xTKAvR2%03B4lVgm13+~ zYi3(alDSz-BAHm6>DzpB#5vQby$POCq=_(P^Nn%zt*hW=o zlfw=Gf@Q|Cm%fB#(Ss3ZvE+{KkCd!UlIyXEi{@jE;*RNVnwgGz#*>a?F<}VGnNAHm zmguD|N95vo6^8oySNKtL*KuiwvC4lHbJ_%tbHZi4)~topIb~EojF?qCST#jFS263T zm*B@44^EIF9vi{e5S%wSp;fgMA+UG~E$I6YgCZ712#DZOV?ln-ag2|KTE0vHP+R$0ej zagqld!&toDHEDEYUZn9aWENhuw(*jUeVNbOU=KIuWXVD5w%L+9TPiW(Y|K;*)dV-L zyA`Sv$ZC9mJ!BX*uE5$#d)dlfK{vqcg&z;`Db5KV(}HVxDTZWM0*4$`@oS)Sub*(f zKPoGx{)i}%MSd~4Q7n{V@PMJpvr!RX*I8rQ&g_LrF%ko< z&CEv}Vm@g(O~O2IZVR9T3CNZBL6!=P6g$gCPgMLvX>@_AUkvq&ZhtB8I9LY?umk+> zB?W$^C%=w7jLbyhM(t(j1`iri@$60rHPT0LDSK7P84Jsz2O18tq`7Yzg#acg4&I>D z42zi^%14~gYL%NJO9;1|(CP;#qSTS5&tH{n8A5Q>hHo|E2Ty37YX993iSMR14u2-u zsOC$4E{XW-{QbYRMm)MutHgtKt!#y+@z#T=&e1L%0*}0V|2*6LFTS(CXp%GQfYoW z&U!pP;-D$L6WXe7jbTK?LNq;W6=-gnRYsfvO^Fm;$jLe-jk9CFN&osVyRC= zzA1ebQi-!i2V)C}DSbY9EV!gE-nyCEbTHb-dLPWm2Hm=tcqytyb(+0fFj9z)i@1O_ z%?4x;xu|FfZ?<&{jl<%N%29m8LdDoevzwZA>)k$>*G9j9 zlCx2&7HmhkXiBe0^@mIXo(pxQ%~AZ4p(}bi;kixtpj`vg`gWN`?vY! zi5Cb7*=HTQDrv%1T4EfVS)@qyZ&*vvsDd^Qi8Lkct_E zT6jq+2`-~I0D3WsfzxKhFhrzhJuWplnwZ`M`1CPPK8*(}rd;K7PivhlWp5L&hojAD z!b^X6i&{9$;-k>0Htsyo`UCvH9BHG2;)oR8B*$!>OY1^r>v7b#p7Blc%?C@+FU~j3 z>Qc|cV^W3qh`ZoaY6#7c>U2}Hyl~b5j*yYJvoWhOx6OkVDNi81L?m3EyA@E`)7@g1VYSBjYRCI&@lhnkC zMUvJrag-!ucp|p^MiHu^g>5mt6-<4Xh(nWyA|I;8IceB(k-v$L{ta7IEoZdA@b6Hb ziVB@U4O*iH&X%$6OL)FdVDjZ%5EP@OVP~{1mimquRQKlj7#gY=Ug%YPj(eqSi%~xz z_wqX1+ZUx4CW_m^*1dcxT(ZC$~9O_HjF|} zb~Hc3zxxd*UD`k4XMfYeyB$$km+_Z9gS717(Qm1_A5ZAlkP4s!0TuO$!nTjh7oY?J zUHXH+d>+02`Bc*F8PVvC#M{Cn%gR+7IXJgxBmf8_l;&v9D5TI<)orwUYM_+u<{7#u z0DB+fY=h9G7!~wB8H0w~k7dlFcQQr4Sy_Lv_!u%naYCYR;k(#O>DX4PIw&KP(xIT2 z5Sog#sDjY)RlrhF9UUIji8LDZ`cE@@4;#>tRaq4{=fLf!c<~=v&GM(I{zn2Z18KS0fph;<`jco|jU5!EQYf>iGms>0_~zTkJh4$(JHK zBI^u4enqR@q~B=?^8t)%_67f$g?Pls7yY3%Z9jbi31(jhNq$=#kYZDLlY0s4APLk* zxIbYyy~tB48O%7sQ?6IT4?*UkWlZ@f|Q}>}aIshcF||_LT&J z!2v=<2(n&AwlbA`1sSvPDJzAs2rintCOjtdaCh!6r0&IvK7&H{p}Y5P(?*8OQ2`!& z?_XM~#cZ<^-=*2DDPFY(iPZ?pv$;^zyH1UG0A<YVHc~5 zB;^8_f36Yz^qB0dab4GH*G0jUJuk6OW^*x7l7V-AjoPDYyx|Qks>Q1a0k&kdEba2~ zQ35O`KEZW@{HP97-Q#@T4J}~s;iBp^S*2LD~M2ujPRn8H8?qLtxB zBLECB1wiV&UO>)i+-&!3hDYtFSLP#cM*}SL?>CNs3zDRe&}u0;a`GT3{`+Tff`p9T@%Ws+_JpGEiI^FGAc{MLe<5wh_$=4 zIb>}e^`b<|Y5w6YEfi0te{oA|QS})`FPEsKVa*-JFW=HSSFd90DtRYJ08wUHKa>wl$8;62-dsO5-w5Si1){`JDI@5nqc*;gS zI~h@;KO^mi4#X9gCJaHnj$mc)1+?-IC!jaS%^_nbKDvYCuvo96Bcpd_ecLbm$!#sT z#U~U5V-T7=Yvc+tOa&o*IfK0Q3-4L1)vnwDI2vkR7yI*haxqpA-@@T3;{k_9=-OiC zF$K>bTo+SOCxQoYPZrS^`|9t=Ny8T>7~fLR7o-=apdO& zFpk1szu^ckhLQirBB#GM`3GBEfJg#-MbzF_6+WG1h*D~A6Wp%UcTSrW*(CREEb zB8QD-;X`NUBCg_{vq-~OdEtJ|f57)JX-o#;S&OT9i%cCy7=qj+k+)|TtHUz za>dvd<7JihohCGE3~o;Q6el~(_I(LpL44AX-@S)ZQjO#i4R(~-EnZ?c=6vx&Mle;Y z5l>SD_*FY89gE;d0do55SIXTWN-O=!@k)Rv)x=ssR{bQ6NBUP zkfaX~VpWLDUlO?&D7Ts1GnG4(+#iwK7JJ0Fn#Mv?bad&E+5YCaVUBmqMquqdUD|+X zb_9hW59}&i7J=lqy8M;MKM#J$in^X^W)(JY5CGMHy3Yigu?m-#6AZLo^$Mt4L2n-- zyKy!geX{#@j(M(3;RTPW$E4}1GBx2CfBU{xyIX2mF#P<2w;&J-L^gzqx=)UX6$6-a zO2U|gI?Hn1+ik(SE_NOe+?3u=2AA6q5Slt1WEV>wXui&6Z-xYR$!?=#*}J8YW@VM8 zpOS+5VA*@*1FcEbU9uoadqjVssAVR9lCL$<(s)P#-X5PL+fHTpSb+S%hepJcmy=1a zENUocon_~Nn!`(CBH6|Nu}*#xrP?SEnE2L*gHfcH2_;Zw%>TV|jx9RRFP+as%S=J| zs)w3?nP=rodC6I=CNF%bH45yzkBVR(O--lZ;ATtb)`jqWyy_z?cvsuU+dje|_QXjg zJ?FybR4`Mt2nLicZ3<&Hk`cM}B3Wh9Sx%ZFAAl)xnnI^XagBL#z3m0`x#{|%#c+VP zr3h-^;;o6H@{Bd*xH6$J(`z%9gzY;=tkoZAiI>$fih9t)>+ieLjiD!2MWs1sRThY%y{;|3~25 zB(PrA(b91A&V`g(uD+#(fWT<7U82#ZCITP6lg_@*(Ir z0yNr%pPv=tXDMwsBz*C>9m9J?h{!gdYy`b-dD%87JX2HV~pa5NLx)SfE|PpFY8LMmxah z?nvk#{llq5OnXV@OYqMLUS3{qZx4UgT_SG&1;i{M_MeggqRtaQHWFZI3lO3L z{rr>XlHyCh$lT084B~e%EqbEU?Kpf?3!@5$y8@<8$*ngu9Hi{mEN&jVn|rm(jfssQ zJa(e5#u(g)44?`G8fkzqNCW5rp0v>Yom2(-DyKVFU+Bil7tUY>7X3>%qU=k~B=ibb zUG9I}0vBO;;>eQ;a|RA~kkehDXSu~$-wDsvo4dKgrQ1>m!>?Suo*QC;;Z~VyK$+U( zl7^mY@S@OV3EkNZ-Q~H^f8ntRy{{Yk)#uRpCs8u=pWSj-=*GxJH}^F+_djm#TukIR zBybyZ@D8_!8%+f_cQrS6Fx(bLfF^E;_HOQB80;w;+#lvltUzDybm!{boHV)mVOLmm zpt?XjXl4_syl4IHh$$DCh6-c(4^$<$KpUP5bQj`uM7Qoa%vm?gs^>8K{!h%8z*rp7 zt#Ad>H@cb6PB(XsoBOz%`v;6(9dh)>dV|AV%gsH=&ArzZ)}rURJi6J9iGFVG$!_kx zZti#8+&^Jb)RC}FdJif4L>@<(A0x z3ofQ2-QYDGZn|9ko*U5tx3ciH%MF8h{IiRx+b)>_bIA>J^Epi3|B2aTU@T;rH(Y`A zdv139)XiPNP1M!g+y$6ba)|w|o4fYUF8DsTg4y0J&S$@sSe$`9-4Hb6?}#+q4Q_IC zhq<`}ToQylewNR9s6yA&$eOCHUOR#6ri-B~fb`oIH#V=hW$UV&`>Elk02|!s@3_&l zcZ1h;bH^HPmHy@9NdL4e{dl{j#ZLrVAs0w(oRD-}vYr^jkkh zmsI)b2&X_o`&&~t1D?pud_XzYo>j}@bIP$G_RqI`V>vdO&Ha}9l!rh0Ti&uf3uFVn z<-N_`gsc{ZO{ zfi12&MCKWH>8Y!F{5SLPimXAEV?UsH+rt;*Ba(LVF%{XUY7M?YUXW*O*2QjsYa;Di ze!e0Lw*+lNc9M`CW9EQfyn|G6o}6a19*U1i1~~j1O#L%#ti}FedExdIx*_9I7LA{9 zIS*lib>sjmY~N!Ed7g9J5?2rl!JsdVQ$f^K3~CRiK0r8?UR4h#!B7y0;~V(uN~}px z+9pc2SWG3h@vYucj%dX=`1zX^STxTl&)Tw+-znjp-sljG5^R#9Mf?BzFCt(&6`;l@52V`wty1MA}M+L%-p^{;XM532>=!-#3N| z54cqLDQ=k-*;z`3pTV^LUn(S1bXOsn;tMJqLLi3D$P4S0 zA|J>r!c|$^xC=Qs{SE)npM7Y7E&adr_!;o-dbE-M`Jy<5Kn^{QBahVMnpG|x6gQLV zx=ru%Sic0^&|~aN7>1yDoFT-!KtPW_D%xBEO-F1FJ#JUq}=RA%E@%vzCKFk+-gBbp&4sC-}mEIn&ReE~{7UZ>f zMjbk0ozh$9oyeV0hc>0#jt6ewkA0yxWZ?g$w?N?C^;U`e&+F|GjL@mKBJxPR)%(mP z^NFESwiBprtbnXK^p@9B>1_}p?tU)y)=SZLBTxxqbLg#|f;S_0K1dyU+t^aZU7g@t z2yW=DvZ8-_1n?z*JM?yg0I?({=xv`5Fv5?1%AiP!32UU@npVPE4e71HN~O1=I?7*N z`b))m!(V14?;Xg(Sm9@UdLV1fR(-~^0@*s&c=e9KLF}~V6TFP{G3|~y;u*S2)t2q( zREPblvG#mNtzhP>u~g1m)T=$@9t&nMoWDcQk6O-;)?@WX zW(9-$O3Nuyy16Ez5Len2n#Uc&yfOTGG)?UdUr1=QtU9bqy8QIP;?Ev6l-%2v@m}>=lRm#LqVTxXC<5&@xc-6snADvyAK$c2As&;f&=uBVE8yZ7 z?2;rEauqYDcU7N1PYg1ka~JcR`YbM>8%2TlPJgBw<#A=DW6r+P3f`aryTK+d<)#p} zoPD`~Zwg_p%O4K`Kb;oxDhJP%x$ z7V+0YS^X|H8>MqA#hVJ-T(Bg5U8?xoIu|`8Cx4?1=w}G*>H%l+gl6nRHflaU+Ke?~ zk@NYzW~?QvG@mzUj_>(QKA<_9$llK6hnurjEFzQNZ_es6zf4}U1xsfO=J6FR*vl+t z9>3KBoy_?Q`G}S*i`AXWO|4ioyI|-2TCo(?XaPUciiNOfJHOqEO=Ab=@ON6XvF!ah z{9J3mThHMotywP~+MbAY=c_6fU|v14avwpn9e zf5P92X794YY5ccn_C0GgozIJ5i`a*s>}c4P)z{d-89c5VYsQj3;_r83cLD}Yg-Bsv zbbH|B__(xU%`ER)={%LEc4s}fzo*bpU}56Zuu7kOq_nW`qmqRyp8A!U zg71!}A6EMJLk0im!;*!O|N4iVBR}lqPkFy&9PYK01C0=I00>$++X2EU{|1#=iZB0n zW_^TtJ;>eVaulRb#0lIZMn%?hqI>ajj4QiI2&AB1*J<^WDgz70kPPP zL;G4qosW58IBPVZ2Uf9M`G~{yeHbJaOb!sw-dCBqk1ujN*%!x`iD|4w0DmG7*vxyM$F*af+363twH<3`S*gMPA3?N^@+99X(jkgc(Qh)P@ld}Ek1CY~ z;=+3>9$&;KTBkaO=y~F>MIrtL!c`o`WXgcJJts53V<3iO@=joSMG4tPMtXUQV<|G= z2t9X(?1>lw-udqUo??Zf7mGlS9Le$92>t!{_>frEWk@Vxv9d4wy7J_p8fCVS@M(!i zI9Wjg6(kyv1O=&}AWr25iHDE?Nv(J?FOFrt?A&Btt_KDw8$Y088p#jzU^Up#52&ox z;rDtlGut|KM^sPNODl8#gA%@cpf;&Ymq{huXOI?HX3hI0yyYOR4$GOiqjMblRAZAr z=0Emg`7C}SU(lPS*8h!69MvMW-pCyzHm?HY1FN*we7wIIB$g-hw(+PPhECua@oYZJ ze~0_^VN2`InLuokp({%YB~LW&-lWse#qaVHeOO3voI#Y}PLxQmJz!)hHoeQM_eF(O zW&)4wi^gKiyL?Dr)|_>Cm(T3Wk}MDXaR@XS$=IW&{tNfq@zDR{u>|nGQsVEi8^>lm z&}AxDibw41Q3t$WRuzF(4#Z2>cLQoCI103sk}S zKk;u$;cPNo)W1(bbU?Y+KY+W8;%f!DA5P@_W!5S#a*4w_Jl<-j7a_7SuZha0WD;-F6CWFrCJ z9MAjoXa4-Ve$21pA(9b#D;<;hseb4bl$*>S^_I6`e9Woa_3pS5j zndc+^GE&K&o!|!V;q!Tgfvm-F!t^JrgL;01B6l}dAqT0D*HICQFUZ_&lQ4Y|b(Z`u zy$L$(X`&R08KP60z@|zv+`LZD0A3g4llX#xEG+Z~#7eQp;9JzjusUhLl#$QgP}sEb zyl5b+-)f@t%O&7fNUzuQJ*%#x_=>?$T@4ook5S;7-V(m1WtkfM z_F!~P_P@b{hp^k#|_zGPohd1$O?;5Y{A?FyE7WkT$*LqLL^i1s0L<$7GfoU_8`8A3$;@Sm~>irRk+Aw-uc)d=> zCpU2XbcMe=lr^hdm`I@V;AY7czJ4fcZCR%3vk`L;tshcy=*ob{65Ipu7+ZTV)Q-Gc zVVI7A$8-v=RQemlqYN%#q{>|faHO{8O{XBn!&^bFAYYI2!&rrCA<|ud3?{eoS;p{* zud+5FH(=*_kjxWiMu}+WYa|U<`I+(u&wrIQs+I~k?ErHWm*_uu3EmQ+OrRL&@?+%nXH~t=7BENhEd2$X2|(aBf|q~9DOly-Q9Xw zy^)1&NYDnA+pOWr#2ivjzQ~V{V2xT#k#LtbI$T5)MsCwl0jYgMA3#E)#V}rPBzr5U znW{uK&jOE0Qpuic;D&^k&*E!GvU(Q683q)`^;-W~lna2WwVx^ZIuP}l{|osnH!MkfjkQ0L4?oP#dq z2&g;yXybor(#-_EE5Zbe>z0RXX!H9O=m#m!q1gtE8Bpq4aq2LDy{t@7G z`)t%!@>M48jJj(gQK>yA13`q+g6$^a#vm6(nv0^1q`*1eQgH+n=o_1D+;23i#*0Ux zqmw~qgPc4Y!K;pDVUfKI{~_omZJL*6nmZERh}}(Dfan&ZWbC5bc_0T}{&)-i zao`rZBO8j#*o zv6uVt;8?PSlRA^i*itP6!9o{x69HdKT`1TDSms@ z@4sPi)E-fZFZxj0mx@+9vhw~^SGI=1ok=|%LdFcnLOQ$pCbx}aE!ehK`0jBSk$Aq$ ze;tRZsNB9ha6Ec=%lh)z@vH%x+?T&S9wUo{zI^U@WW7UQ{?&MdtI(I9#<#(5ly2HB z?AMd;o$s0b%1{__+EV(+h2UL%c*A#C6U$s8bem)G6dx-H$Z?e|z5DSLdw9hd8DU-` z9?M9<9RQn>DJI9=`f)PIrUbz7=6ke(8fR8-zKe>PkdaMI2jH0+iWQ=-L4jgy)1qB- z0!$?x3`lDtsx9u2K%ruRFKu1La^zn{>s?)v!gyX~0;_MSJWnPe<8mdjghIPz&R?V( z@qKK>SA*i)O*gloQBts!n|ROc&H!Z3p620{S8o~Bo+Ao=jy^IMZ6w^XXT3t~bRq&( zfY}PZ)Cn)6;7JNT#R)I!O}y?gEBFv6{G@`1DtHGce2;=(?oW(HrQM;g;c{dS{2^(PCHln(U=iraCD`Wn7uJT-|YY;BE3^H3}b<9L;K zSzy5TL}lBvQ+7?$j?hQS@v}JI?On_oza7UXzsnMsUmVXT|8+Be_%3FV^Ud7vJxt=P zGV|#7Py}b1`4IAtH1kyYwlnkf?}5(O%ztV8FlMxM45%JGbSml6Uuc{clCCxyLep6(O&-zkobt`^h;7|4CH&WP$s*Afj zIFoVB?9PY0k7=57v-tb(WBp{z%Y5nkYxg5RilaMGmd2uUfdg3-_YehdPVno1cbC&BwaL5G>>}$7GI~)8 z?ejrULBP}jd><49<$b5HCKY`R2JCTs#uQe)>bV%%RyvyGWx0Ia6tw57C78|y`M#OU zf1ScwR38HnY1_*|+c1~=f5>WEYDNQLkGh1`NW9%ux=)gOB-~;{7YR5-fIbSjo!l{m z{2fR~8#VnMhdWna<#gxiAGx_Vz&*w_&nIV|V|ez5>@AjP-cjcxHdE`{ffB?F1fAMa zD-MkSkrQhZ9kWt3PD@?AgM*49l$d()32S>)Kf+b+N^?~Hywb#ic7i^wZpL!=b>$XK5BFV>-T=t3NyOC(~GP@S#qGfm%eUL6b#E<9+8~w0CPe@s88k$e@bn zB_Au_Lc&9&ggocN4fTHd7T-3VH8B%rQ#Zv$1AHMd^rZXI+)90wm+YTq9PNnmZf8oB z_8i%x8d5~K`Up?viC;Ub0@K-oOtmwj+tQUMT3DT+{VIYTV-Uf6G6K&{aD$1pWB76l zYZ6G9JW>cm5hWFaUJ+FtK3(`l3+u)LJMpQhsOKhi;k{F_+Ljxs{DEEgm#M6EMO{X_ zDCCg`zdc6_;15$#>^F4gzB5=W@6ZUcb!pVMcJqESFt2l`1A%Csar@Yc8_$Pet^GCxLWiu=9^vrOKq`9H zL*3OWwU9mM9EfJ`D#gEngZ>7P$A|1_Pf2$ue!9rv@b;8xuuDNWC3eejs{FEkoY z4@p8Zik9Tn9syWyD9#yUT@+%L$M3vf?!n)(v36PyzRJdGR#-|FX7hx1pN$1IjYYAt zmKWm{bRT(b-WTO3THw8`vWaw#+3tBSj+dFk+BEozWQ-w50vSr8C@;g|wkFKi?xwzi zSl5vcox_6h=JH2#*k+c}hMN|!fNJU2z~DX8bYDL(ZK~<(--i#hV|5z&oNC7;aX<@x z*v^`_nnPvC?it%#AuJD0T^0H_&{T%DtC1paX1 z2ycZx6qlt~J*_~icrKH@Vbp52?=7p`o|7po1h7rf#*)|OJ*F35KNrRk%k$>4o)r?I zS1?tt8~2^ZzBb)~IZ=+iX#Zr|OZ@0O){uSEn*TkIeW&f@>oQr3;J2HB#)`TC4XVv} zGTs{NW31^OYl)YrSy!((q-OX0v@7p4p9NURhs;rKO-=AP8gYy2*$370xF#w|RHL32 z=$PmP@Zw5aLU<17NqiGaHt&hjt+ZDtbL<%}LEe4ngOE-+K);3@0(u6Nqnro!1Mmnw~|8gOF+N5L>72dre36y(WnXAJ4oLj9%ykHS)Y55jq7raIH zGtzlT*>Uh@^x9UdnkL9Wb5ds6c%%;J@d<8AFyoTpXh%@V(k7y_<{3xsResS?8$;32 zWiJo~!(ELXmZJ|oI+XI~$G=<5sx_J2z->~}U0C9K8EuM$o@6GrdOskg(O!{bhbwR`sILODP&Mj`b)(v3us9wG~W zS`OBUjT*-8`BPW^^Ac8L=&X7a3=fK!jp?1yO6H!4-Ck=3>0iLbEdkrvIsN+#% zP_L`cBbKry?41Vu=cO?4f=2w|Qr3={8t_)jSV+^cFf)3wZ$0selHVG^^|hFVqu$BC z!4Adw9{hq&TgEzCZtal9H$9#t4r>UP>M#lhZb5)R!*3ptG_N{nsuB(2E|ln~t_1%t zy7#5<=7coFNFWJoYi7p zAv>-u#~vc@TS3H*EdJlE;&WEAmO(eZmmE(uQ|pFI!vH42jh<1GnV(t7np7c-mGXgh zO$*`PFnr4@tVy;~(*8fYLY#r7GduC&=U)w;3P<$V+;IW^xFz*Ke4v_br6+G>8_PREN zw_JwCS_r@aIMzyHw#H#+pk+V)TrN3N^p376p zM=V@squzlG+pi^&!9M5KMi2*_08zD!mO!+Di(;eO9`q3Ofe^0rOZ1Cgr7$+$;R|#) z$lq4R5%m+fLzVj=xr3BDo7_IN@d7iRmL>NM7?@aB6F;l*<4oNi^)9fIt0QEB?p%F9 z)b%BGRBwvoD~jWF035yLx)@10+#TKAfo|@TJuNPxolZoaZo?SQ5qQ5F{HP1=&W`?f zcNhIdH}@pBuy6iX*r8=Z^lQ!ld3uVANH5#d73t5;h;sF=PIrOc&PkK^97CUX=l8$F z_~>pRuf3KHVjqs@DQn5^&sVNxJ<7!SV~3J|kUuY7%NkVN?F;e3?7#Ef(R>{X)!4aO ze9%{HD4SM`Z~Y2Gh+(z($*=(Ab8c*H?d`dOGYZLGTs`2xifd8Tj z@AM7ub*gfo&A^}b;X^kA|Gf{Nx*2%p&41qv{B#q~+5&vINrkU&;(^}+|3)SL@wY6G z6?yY+S*$x-=gqBI2%qN7H)R3;O9fteD+@IFRw9eVBi*!l=iE2E-Bvc2B~|A6TUiGC zqZ04)9flCGUVPbi$n5@#Jo$Szi-lL@kH1G`)hqJAZIoC!{_!^UHLFm8H_T>TS)Lak zn+^PzUfh<=UMur=*%E#$8&ph0=V$3#Uc&u&mmS#uu&*3{ zcL!Mhpd8<^1F^L!$Di(C9m_oQEa4q?vYwXBp49SSrcS;jPIuDYL|qi$pdP?$lTA_4+Zd^CQOFT$xAC%Q4t?!W+Xy$2sUGC| zJs4H}SdNUkKy)p~kL_W9_?&o3Tur9eKnuj*tc35|i`^`|96!4kY5l5|?5Meqy~;X` zmvpE!sh1;f8GF@$_z(o0uMX%Z^e|v|(3>Y1ZGC>}DPCYW?n@G5(z&SQF98IShS6(w!-3UVC5E3+v zB&d_~6ghX0uW*t7DFw0!J8=}bM+Z2F{+Jv6J1+WcgI+!`iRgn3@|92d>xZxl?Fk7A zntHF4uQJvKvrk~S0e&(=^-~2uz~Ez17fx=p7_AQwv-2aR{?8P zzW)NWQ>D*%aRC-QEJ^R!|@h1V$3cDL)&K(7FH^y)7@RxpM(M{eaoE#mD5AjO5M7?I&<#qI$dlBC5 zdA_`ZC>*Zg7OYh+dinz39!9mZb>W(UmCVYJ$v zR{y>tO#*2mS??GkqnQu%)5p5VUY2BwX)J+z@KW(1;s_#EYw?lcu`cTRidu~svR50_ zm5CbCqNwlC8j>n^_wVouKe1MpSMEc0C;-Qxa9nAcstC7#s8&Fhz$VcKr0>VnRoE}P zF#AH$WX)074!00CB7@j7rF{kx?DRm+!>1s$7-j@bQ}9H<6A9kUfR6(_-rjoMY87X! zkzzvw-RHR!yBH}J+{B{?tdV6Fm2i7hs2@apRqD|x_8J5`0hmMVN3kepWO}C}b&7pG zkr`s&PCfO6*nWi{=)M z*vMC0!M3cx2tcDg!-aZw z%?jD2>tdY`uie5k_y0Hb)gfB3D0a{XC=}MoM^W&^-Ux&|8*Z^?H*m&c2oL`68H;F6 zcYaO(kxmJZEIwlqqEoD(@ck6E)$&Avi}t+5a&DmA+`q|Q-4NTi*)WY4^R+9Axr0~K z4uNkJ2rD2`_{|diuB17xzTq;JV$#lfLhS`;Uw<8L4`1}F8kzLB z$tyXMik*5!wcjbySe4s&(f!~ih7*6^WC!y^s|&65_PoPJ-V!Yy_pg&u_=}!R{n?^h zVpWe_AQ>k0Wq)=Qqz{seSdQ1AZTho+Zs9e|2iI7O+t@XeeS^)ojfPe!kFCFr5%8EB zEQg*?-exaviyfB}v^ALCDb&@Jrync(_!?O#%GOkX& z#me3htJ;#sacvcup_)B6NYY{tYbV-z(DuQHpp7&>NEWPjE9rXFVh=l=q8aa%SCm8> z3No(gAuop(k$Vl13^zPekECEqp+<0KOW*UXwQjHrcf?vvd1FI0xS)pYKKK$QT5F{t zD8fY4Bydl{M*uHA+DCac&1FsQiUBoVUFMO>qNdeaS2MS#z0fy(?DnoT@YE`6&|pbc5Z#E7r6TZiCS3M-;OFtkh7#YT*a26GE9N zNsN9s``FQ1-*FCG+r*(hmHX{XsE)#D2gD|E)Ow33~%K9^Zz~E*-Oq)8nnGc8NVzv32ImIp%E_8@5?- z4oyGlDBhaho0vySzm$S@^zark6`|xnxmPvjhQo-K-uQkz*RneN2AgdcE1R2w%$_|G z%dvxY%uie|vT6^+zT%G;SkeQrNk~IdDa|{$o~FmCfka4poT#su!q1WK^tj0GJP<=- zQpR$f)cyzMzJH!%pqJgcrfHN7O?y+=uL$ECcOcMcN~3p9J9&~F!^zEpYrC_|Ct9k= z#y`ZwS)hu8`X*my%N~l+js8AEavZbLsylzbkU{(%L;M>Q3I*^?p@2AaA1BYS@{hz? z9ai#`50UaA-6V-21eFbuVi0MDkuct%(dc2MLCc{W5RYDSe0+w@c_bbd|2o4uJ%&&0 ze4dSaEPmL`Ohtg0(Z3aG5zUTzC0)QC1=ucaURJ3FQcuuk{LVZY)*1BoMe5_T?9O9x zdt4Nf6glm14Mldg-&dKz6;a8}WUQ;02E{aCZ^|-1a zR#aLq>A+)t zG~4=A4D}p7lGkdlm&nTd414laEMJQ7=f4~Lf}V+fHMAX5gMtG(6JJb(}^7{ai=38hsq@`qeS~ zv?eT!ewxxxL;R563XM$P#K$l8W;AS8hzwWW9a6-guK)6?U735~*MIANojh`;6MoqV z-~Bfm^Orc(wvp@+D^%R#spa4sI_kF&A`<6w@v?SQa2%RXWcrTDQiP!HJ3_G=|AL;K zj9@>i7sVxan$5L>$ti9$MC?6?P0cPKiNkl$k9=)%E-X_Oj zXn|V)7DqMI0kABJf_>p(i$HJ;m)oDvo!z;YVkKp*u3)tyLF)a~u`nE}z7B_3saN7i zr6UFg;BfQ_SlYO)$$Nmq{952ZH7Vr0t`oH*p#2VcqLTKwjAX+~-K`TW@0A$p z(GNv529s6VGXK{YOxC1QW60?kOg?DCdcGE0*bZdF!iUk%cKkR72{*7b;J~jr;V+!< zzl!l=_QS>a5qp6Xe$NR{1g@Xq#^G&T1yK<3NmMHHdLxeYd3y-L(O}?UBD|#9>L^?A zMqJW-FC>acvSGq9-f>d(uI>r6htLSMhNv`_-K{rn_Q}$BxP}!_Nahii=^`oY%fHdv zyrx=$Q;0vo*5J9<#lv_`UyYZF-0#Af5B`}X!=+z%Zv`4m_LVvS`XaZCU@}ZPiuoh$ zhoRG%uhh^3#N%M5&O<%?3-kC#%^{CGnb&eBLYh1wLZFS3k!R*7Co>FDY0bP>0p{Z!km3 zz50RPu=4*64#9Oj4(4SCR;>Jf=25tK!NL9Q0CxCa$og;q%OjXOfN2De4Pcdv0JjWa zVFZ^CVEqUt4PaA?L~GTt11btspln4Th5dko(WJl!)Rd@trzfhO*(|$A{MF{;ptZ}S z%4xtg*9%Q|VkUWv4|qG6o{72LR(->=l~fL9llQ~^CG2IzsCu8D-YEO`<1MKFebl`l zI2l!GR92HcjvlrJMYxap-&ft}V#6qK)@CEE3U|)oNt3rJC5J$~j6vCD%*&=RrKCm6Y=QQT9j^Bg-`1 zN0vij%_B-PD!ox6JVY z{Gt=A^g32uhw#8K+Y+LBY76;tT{O zDm`oCCw;Jp{WI^L`cW~`vrg(H-ql3yV;js;HL=P*_PbfCB+C1k-7M7-bN90HveZ;u zvzNul607`Tr_t1HGa!2$vOrGWdQMk>B9{=Qf;MzzH?+AZzI&m3NCYp5qR(0WMOd zknO#=6&$>cN}ilWO5pcB!L|MXlEXO<$Rgj+#BDe1h%B$}ewODVHFBF{JZBzYl}kw% z#7;ZeU!|lf;>Iji-c@QW{;`8~cExj-EEex7)eyhk!B*0>&Q_5|IZ4!LB!Y!jW_SO^y+}S+CMya%ekCEG=2YD!bY0(o(QEbvrv!8ccF= z(RXR7j`;m9R?baoEq=C(^>&jQdgT2?hQh~28|t$aZc;6`Tq-Hb@oWz}<0f_Sh$)Fu zu0E^bE>-pI!lS?nQ}VbNC)82f*ib4Q$wnCgmctZ^A> ziCA_E`?ZX8uSVU?l>H2ARC;^9;v%aGr?dot&O3M|D_9p$OKoOXJS2Zn-NascNFnVH zZF)c1CQd0yb`%3jl@T%NcwFaZ&nF&26DFO}M^rEkdZm83i4F0T#`&D!YDHQ2{fVl& zC9BX=YHISCvE3m#8NT|>W>(Kz+9~$_krZ4p_@#Pa3;Bf&ydu)tW!f!hy5vuix9R$e z-o^rbq^jb?EiB4M`bccHg{2TI+RP67NVR;nZgpf3P8pp0krnw!|MPhbb?X|VCWJ5Y zv0WcXKi1n3$!+n{dDvpc5AS=VE#Epk(oTvna5Gy_R%%%OG(@DTY)#PUM!s0ja?47w z;=CVO179i0BWr`h0z9TwXTSJLjl|Yw;D4`Az}(PWU4yeClPE;wO!6=ctk7!2PRp!a>7n{i94{2R1=6?Wx(w4^iu}3AzuM)2u*w~8ykwo}91?r!KKDC;qRFWnro0@WVVZS2fYqE_rxjt|VMr;1c zd@WK9PYUUT)MTkgzQYH{B&*nMJsWM2>XpfX==v`AWmdM)BGvw2ITglf+!D;qsv1Hlj+^{mR*mayG$4!jU;%r@3+uwjtaAL)=bM#L-wNiXq5{5Pze#Xlp|V z6xoG%zFDX9v`s4EdBmCLP=n_!n51KYw`@x)f7m}Kz+g981XS`AI8>q%;KzZTG~&To z>l&%2^G*nE0|xtufy^@)bV8j@Iru}3sM!5sJcq9-LNA^JCWJ_l3PReB*J!WmTlgZ! zk@6oXx<2}=&SNjmqb8lkTQ&_teZDb@`6VuQHB=`#7jq0UC)E|Asn8zrr)u;HozjRx zFo}0{d>kb;iRWLN!f76eUPB$rTZd7dY5TcDF=~4e2T+}_BupbKq&p`WX`)#eD~=TTCVh@Y2F5-${8pZ$Xm%daifz-2%*F3kIy<@ie# zKWx>4E3NWzDD5g5qpm1utqf7Vg6%r=)sSM6$sJR-u4dNClCSvnYChMsJ;%($VZLP{ zb;mI*ExMjNG8HQ;(P^VFZBKppuneXV zozrZ7^zpdvQE6jCXoS|R0N*jZMB{qzs5BdD>Xw=VuDF*jATm{@n`siGYvke9-|1!f z%{DfT9c(C;s<zgI)3WNRcuFq)V{;D z=A_Sl!ISCoFNmtHedULPb;oGgm>OXe9T;`Chf|oOMWs)~;R(YU$P6B_aH|v~-uB{^ zYvYG+ToF-ixEvbCnhPz9H1$fsPJd`=)4OVJb~B-lV{=2A<4P2--lO~#GWA&xG($wB}#}+9TE&3 z7e%Jep%O=@ZKOJiPF)`?m{>#=sca)}L?boDk}Gw^15MT7O3MO8Wj^*wUI`=`uH1V+ z)dW=`TTn&v`@jQ2N1n*Wn1#lTUMU+qS+gLircY^16RF9C@P$>i=GW|CRV*302TFl9 z0bHZg+fo&jTS;9h{CFbRs=HAYF!bnD-I?OtZ8*;NM&h2wXp@>yn)~dP@YB($n|Ok# zq#`e`uR^iiADGE2WjF3;j_}%T4xWP(8I%bfMBT(4G--zX{?8M}vrU0gfNvfihNkLE z+$iavc>I+0uY&dR*MU+!pU-eluXDMUvZg^8k=7`$7t2pC)(^{zi&eL(g}QM^QJTEu zMWMzQN|K-$6lP_&f~1PJO3==`g=hoO^+Hgy;f07ypBHRJTB?{Bl!*9HEqhbS5dP2; zE)C6^AMA$&UqEk zJY~=_s)gEc8rYv0O6#B8xL|!vVPTgVJ5|fGzly6RkBeu#X4TzdteVIjnb93{rOaOh z-R*&S(_gE|X34=S5_%<{poJD>5$o6`a5JhQTz9y`6YixJSZv9uMMG0{_rcqb(FBd6 zC;X@A+p0;`KA4EbrFV+%#!{=33U36EWC5-zmaLn$w5WJ%&nlXwbdkFpD4KXlK`yF9Z@oE3E@qcQq}n~vo?u8=RC>pd4v+>M?fc3z>NSpXuWQIl{TsR2 zJrl+k``%CKbLcsq&)QWJ%>6P4s|*lD$d%yCWi{o{u^~7 zaD<6aY*dnl);tGo4j5YV6PO@;5pT}aR=Gnxz?&(&O;gl49eTk69O)&F{a8~9XtEVL zeb+nWfQx>6`WPpE@!&`5!zYr~2M=FXOA4qkoU4ag2)&Y}c1C??9&1udsw?ivU_)z3 z%}m2tW-Tmq49s9Z*OF=siq-3iT0EAK(cZ6PTJ5MNy?WC3gu|TFxoG?UzmA?h^7fyO z-oukc)t2xTW>4zrt2DsyAdZFyaU^|nY&Q2wPSexH(*Qv)RC4fe3Z{X=84s3?^tQv) zpFqnz9Xub82#-e*>F;ooMg)EZaup z;guXfy*1vbW#Y- z0)uc^O(=<#*49S7*81XJ3k{5Bg=l$J*pU?*p;Q_ty*HPFP)q;QNqsw4*NSs_7ZB~8 z^6JHnf{=PKZRw4DYUt%`WAtb=hBA3A_*W(YqiMbxfzc`U4I4Ag=9qqZCEq0fqEoj* zCy}X$gc!sh-kV5pKTeZYM=y&zJjwWYr=Ka{jx?$p>UIlKb@{U?C1~_&{hUEVL{5tY z?I5S=6J+E5OVnUWGI?4s4v(C9l&0GHx91`TL=43D=Ms?~p-^q{?Boqy^BI|Ho2}1F zX4AZ+xK~Oy=9@VF+=X9#t25xk*PC7`4e>VD9$j(=ZOO2iwf1g z^Yl$8PmlzwlSMR@NH4%cJZ;p2VgTyz4CA(yU1$ij4JOi%$leMF$;{^> z_P!{Fz7eCi3`s_cWw>RyxD4rdFeV+2B6I@DJ`O)N$4(A@y-PbId90D#-W7~Z+v6ED7q{ZcJ}rSk$gQrm4Uc@#%2yi|`E zQD$QUsZ$1cdOrh@>~VaXDb55N8KgKeaHO`kNaa{N~0ANdM;?qCHhV;$g?4o4ua64ofT+@Wv90F9ABcp01N@n38nm{*&&ebGjU-boW)i5q zsU<$iPB&5W#>t0mr@@gtv!DGI+)4@kfI;`R|BvtLL0jvbVteeBvIPMcQ1R2JhVSN# z)))zz+A|!Dlh#vGS{d=ZIhDI=8o;I0qxg=wA_PD$h6$rRoqP0Tl%3>Cpsh6e_@e%K zb(9Ud=3_SMo-z4BmzGHJ(ACq(#Ar&#p-379@E}BqLy-Mn_?rx!A@$$j7GN+VPy8OU z7|!f(+N(E(Gtxs!t|VB{ND8)9=BYOoi(;k3 z^U*|L2F_(PL>ilnu+YgzhM&V(_Hr_lo%p zBkkA596UET}DZ|UOb(RD#h6QpIjadusC7q;!Zx|0Q7)Oj+jN(L*qb)M5_lb zs8;GP0zitYal`HlsAm*$usHr1y2S^!6@oo?_cj0u7c+ z(VqhvB`C?DJbZ0&34DzV%pg*VH}?&jM?cea1{oLcXNt6<_xhQ?;lj}0>HW-OJm~oh zjbz)KN)`R70XdJwUh88#-Jn=rQ^{&0;#b ze?-WKOD?Y5D|m4B&W<)gnWXKZF|YkQ+P4A+P8rTAWuqqJuv)u6)-9crmoyFg9wbxq zrs8GUb^5tXKj-M@H~Kk2KfmAy{mM#L^eZoCa@*;9Z~@|zS7l&1E}Py|wV zQ;N^^Jk5j;)N!>U@CiJBPhIN!r9f$oP{(_~EqE#Kz%!iiLr(ZFc;oMQSNOn*KD!vl zRj5vQWvBSxae7aEzh+=@z%hGdF@D6JQ=Isi-8pf?;yB0bg~f4>*na?yyCy@MOI^br zqj-_&=wQ%l(dx*-e}taNv5hUvpN|l-zC*dkQw{O&>}{mS9y5)dxEGsCezmgEIN;ya zrUWtH;QU~*8N`==$nnXSl#^^*!78+ntZv8fNM;*0jYYJO{OY%%gocUJ3o71~MXI$8 zat;|M5%u|_8ayRyZVM^R6!O&<;DZ8W@(B3kyQU6-pW~avZ>y(JJR;Tqf`zq|y2Xx} zOpOE+NE#!@>w@($XyHVQ(P`}snw4mL3rPjF0ca#~O+fg=gb(QYnb}0~o6HJZO0E49 zCL)A(r6l7eL9x6l8mJnT$lA4%YWhEZU8Fs%j)8T_*r_JOCDpB)!RED+{HpYX*}*Ee zt%H(BkdH;!* z8wUHs6y1>KT1oUDjOfEDng<53aYp<_lXZP$9|J)WlP`m8`$6N_^>)%A(K~^)Y%jGJPflR7+e@9rDHGVG z_R<;g`|)f;2dS6XeLVZOgY=2`W*qAkDMg55eAx0xsX_VHor4cu_6Y8b}HY-ZHCT@*q13F6O z#o^7^7agU5h)G}&nFil(9857Lav?4}kM9}y4H-*OmIQA!RGdjLJuIEVBFEC{^NQ?g zN6D|k2GSBt)SqiBf$#NJpN(aeJ4p@2A3tY3I!RS(#Wo_px=Mfjf)>eDiZ_ypluP;q ztHaHxW5=>@I!P6KFUIx(WVd=5vWp#~ixNp{p?v{dJz+B`tOddxCuOHl8r}Y?8cF6D zNq8;6o;=2omKwSZCrv}>ym47wqNN8W-=o7R4;=BM1pEN%_TenLixe+re9jJaL1jjM z&Rn{pGT)43y}C+YmDxI!DgpZ)%YC6T6%_I22sSPT)jN9xI~jw$Of^Ta;BHb^Wt)aY zqZQzk10Yx9pqvK@) z@e-hF1h!4Hol2S35lnVxAEc6)zT10>vM)zk6drRdieryEi@!}ug zFZL1Ksz3V~!SzFo;5Z{VS5NI@ki!jfj!yo&U(w=0k9@=K_0#hdjNoiN_&0-0tITRw zhs~>1`{=Rv5ZSK}`?!yEQf%3uS^Hu)>+(3(zONJ_KIzBe={YivE$b@<2J9{3%3M7g znu{e(U_~Gjt$ZF4J{+Vw<7a*0jMoiDD9p6dVCLHo6}omH3+pF!5uvE`e$t0!PWCn& ziO2lwET^AT+arThXobn6*L7C9zf`MCYzfJqh4+`9mx+y~Olex-0m=YrnK-*Q%N+m_ z^ZK#310Zsf-YjGwo-_KfE(7sg7|SNpb9g_thMt$jvXk`utS@^qP^#>a_%R8>vu&5l zD#l4|MO$AsFiwgV>-S}w;~?{$KCCECiV+v|VO1QVW)b7Im94dWiYl8>Jq@vyI z61=+;UhXRg{g^$X7(Zff;}qv?F@DURQ;Z+6S8FU4vG{PS6Yj9UNT+-^ zmOC69itc>EiiS)6w!5e-zKM+@P3%OP)L+Wcm>dIx?%YIhRSi18-LO)kRYo*^Z4{-6 zpfq~iYCJA|XB3fBjmUp=q|N`+an5)2z9zZ}mRGq6o|s%w2vBEnD_X+8-9&>JZ<++) z{2v08Bc;*eh_0+)q!cQic)}`tF4Y$g zJYgL_mugoo`~pnYqShTB(q3AKob{2=+%9a%=Tg0JJD2l>ItVa>1U2F6Jfp2lr0D5k zUl5!6VB@^~b`TMjE=Jd28HMTC6ob_tFnSs_xT@773B&!hl{s=iFC98F+AQ;RM>b@X z)Iw=dz;oF(5e(z0?WD=y14oNoH<29}CDm;C1qB@@u24cVK)WlgCj{V?Sg@|rgnZ7U zGevaOc|_`h(&mPO+5_md=V0c@Kn73#nDm?buRiX zlCRXCL8FdYpP}0MOSC6y)Hqf!MoRB7w}W2If3~F(KUE(9+S}3U3jd}oIuy?MFO>6r z#w7zk`BhFHnL-5rT>ZH_t}_uG>@Wo%rs8&t34t5zZ?dFMjSHU;qaynYd20> zU;bNI`}=t==)|;f(!SakVCnCN{R|p$3w?)MvstWQy!4HSYnx)X|NBw4a02?XoYoGd zFFVRkPLP_5S358{L24NV2Y$?6f*-M`71NK{&pF{!o$#?vc$O1BkmLPm z0p^IklT$z|C%mB(&YWI~FxX3KNgtWpk!TUyIjTu;4GH z2~A#HqOEC$BZ`gCtth)0AjVsHutWU=mn~Zm#jvKst=aEiN?YA*&GqQ_o3gK_qKj_x zoLQzxUk~W;k)E6uDfHxxK`}nzPh+?GxbRnh1*G;3=NtL)<@+hH+I_Xi@^PQpCEi8{ z(5csor~Y4o_b7fLfP<9RM;L?B~hxUw7kmYm+A8sx-#WAgSh;E4q~GcF1NMt40JI#m4|Ax3)G%WM$35upqS zYF0xwY^D_0@%u3)7Ajy`OqLs!dNeBavc1N;j~_TcUb2T6k63q!O1)(NVhp=5Q|c%7 z@AOsuSyER0S>_t0MX?U+mu9Xg4hvijne)u}m+|j{|5EsO#eZr1yW!s*|7Gy+fqzf@d*R<3|33Kt0RLt2?~DI( z_%DzD3i$WKe?|OP%9=UPa-^dr_ijEafW~~-tL<)r>(uW?$iAD;&e4aUCta~raGmZ&YZxe=US?ZvA5WFxt4k!SvT{I5pcO_1KHhNOM9`=ZC3NDB|uz! zmvy>o2@;>&V)0ik7F#!PjZPba9lj7g&OVp+C8IkZjwyr-6$#(mNylQy!yHhT67|^~ zQ1Q}~@O;7{pVdAJyA#xQ*Yoi?fBax9Z<>NJY#_;)-ner-fw0OTsok#eB&3J_Zi6u>1Ly#Hrv!Z{x?hU9)s;`|mwsuJ14{USN$;3kMOII=H9`n3usqXgnGksa&n|rL)O-n^F`5xQJk|v~f z5Cx6N(*-HKO;Iq8NhfWiVsW zsauwowt{?}0lie*OYvwBc1zu&qa^GFpb(aSM&QFsFgIM$xLDu_}0l<>6aJk|TQi)55gkTKNNR2f;2?~frpM_!=^1%uq% zYVE5e9lxgc9ID9}=W6OjurTym!w@xn75~hmno2?770d5nysg&Y+QK?MX4!n1U1V~e zWv)2-GQQ7b@$Y{q7xAILt<;sE0F^IL(diOy5(At3_|6P?ZmgB)s*=ji15 z7g_vWOSzhpjNoS^GWxE`Nb;#c%Q0y2pmn{-e!6R^B?ew(H||<0_Y{pdjrxurCVYczIBJ z6tA12BJkJ)B|ENKY_B)J0-|SfOI*S)sG$1fibxMTMPbQKX(~|~{ev;1jU=y0XGrpl zW#?N;RqREvjaB}?5{hHDyu|YIE#)g#qhMF44j%MONwC)?=2c)RFTJ{$&t~8bOBP;$ zs_)600lumPTSaF<2088w8(mX)VCONybfnb+= zzL?!jgb;^zzX787-mo@&Y>bFc+NL$tms?@aDPbT#P%%o~V{S zqWK)_Xt%Tyr^d51yCpCegKXK z&*~-k^sHWj>tk50hnBz=wj4(Z4vhfEjI+fYmm-8X7M;x3?1}oTZq@r&gzJkym!etf zLraI6>xWTog{8bi^6)bhj8{jrUWiiD8a2X3P+0I8_V+_eE$df$8B`6z+qdCeH#wB< zrzs(3b{>AL-6KmtnGg{8&6XZdI1WuW#~2y>ixTK-W91HaWUC)r`g$w@$tXwfj!b@Hsp>JfgjBsF`|yb+ z!uI?)V&OeIWH{-hYkHBU}>dNH44_KQyRS;h1t_9WoO zN+4Ilr|I(Q0ztru+9KR=6PaeiIJ2Ff{v!7g=`{6efBUCUB2>>4q|2lKU-1v<@zq9D z%c)Nfg~G@5w=X-wVxL(Wi(`+o1<%lGx*TU)pIQ9HddJz>XO=I;9miOwKP(;mM^feE zzEA#vFf1E5&Z#8~QM(>vKmCEEb&s)}KP-Nt?=kk^53qP~l$HL|vRI5e%GUg8DPJk_ zC|IQJcO`e2p5#Y>zdjE=%FZBM@;jQ(0;ZeFiNaC#7K9k}2v0!W6J0GzfG5b|^r_+4 zZfd;LKBQBupzv4Pvbu>=nq#2iO)tc}``W)g!iM~1X;-O-&NWl#y0w^V^CRrYUzXwG zxnEeF=azQj++SG2b4xXG@GorDb4z3ITEEb6=h37mk!e$7RR3Sto#&Pi@vpq+^(KJe+tqDy?=feeTWLmrM$|9{8EHer4(E{yD{h5B&7! z{Kc#O@e?C|X1iZmhKaWiv4Gc>igk}3;yIx%+8K4RU8g|KcDyd?sF_3okL8Eh(AUst z{2?~~wWWW!j~+7)G2?Y9wS(_-d#qE6xmnfgL;<%82U)E*7+&u=$lAZLbW%QlFJ@)6 zw-K}3LALpgrGnV>AUlqjbsrvhKbNaIr8pNwJwX)Y^78@K>TgRqapQrkkN>u8HHp=- zvt0kRXeRN+9#;CTMG>#;$*TU=Qr{%5&&ukfSr(bZ_^hQ*l#1e|eXO)e2^8yRu{tI^ zFWbi=O$uIE>}F%|T&34O_&vDuP}Eeo{WIFllODD;9B$DaA?g=9*hZ7mFkp9UP#*1q zIO$=ZQE2vFj`t>f=U(==NvYBG>P}uHG!RV7Fu*!R&*)WVZUaoh8jFzNr4Q48LWp|W zsF6VI%6s^S?r)E&Jq_x-U2MFlOc%rUX8j>5mBT4f+u&d*)GaR zvEL5%rwi24WC!yrrPLRt9jsF+rM7r!JDXBU2@rQ~XJ3~>`26iGyOfeBKH8Dh+Er;~ z5~prvNu`w&;`U8h(Qe8|CO7wH5G!I+zJ{GYb;OZU_bvHsbse#bWCHS}jyPKCwmqK> zs4M;?-QJYXyzAi$uB$h(Z63-*sc>sPJ5^5%k_3c2ttU>CX8xGZ#)OK)r6xeGhT<;d zXFsq3UdlwV_a=79OIabd{DH-LD?R*I{Ew8}4ig^inB^O7+u@WL-@^I!2bSlpRB{u) zqbRtwb^|l}D9uHW?^%S8(xmq#cwaU2hkT7+(`~;=UEjiQsULi0r;nTHRf25^>-6-! zHlWtxe{%GV$5b3)N_=W}gDfOi5-{!N*>+u!&ct2%~cxElj^HVyBRo1dP6_qf* zMPOYbR5Cq5sA;R&tcuD;DKJx4p?K~a*13!_R)j9N0)JX#C~))|Qs5WjIzxXss}22i z1H$#^0)$&o_9`~tUrCT^BJFpL#1K}evhuZ9uu|9Jy~;|sf3p>o|NqsP)~sUT0ZOH6 z>lha}JPKzQWp#=EWaxA@Jwf~#j3ov@rwhJjKL;p{yTk@Ur#ql9j1Y9S;)7M1>a$c= ztJO)Zs~77mE-iyvpJkS)H5oYZKEPOOs}dvbTfvrCm9}ES3U3?*V9l#28^saJ zSwR&TdF|yaFi?pU?=m(jP#GpRTg5H~Dyq0(8T&a%=_a;V#y$v!r)aQ@6;)Fd78?xj zczr3G5UkV?w=QLCf|btVpr!0_u#zo)vxNOrRf!ebEn%grAyaKJ>q>C%Vz#uJGF0?g zPD~n$l@_x`)s>FonMEwIy3$^py@;KxuFMhtUC6qJApY)!Y->RaXhEHE9kpx~0N#&FWPC0c+Wn1eiUrK># z4!fPJ+wB5}-KIM1HdVLVbcfx}ao8;o-EM*CcKa2Z-vI5tMk?cdbpg-yA$Rd}W;(I-}2KLPd#bB`Wd-PB}y)Cud(t z2_rse-WzUEyD&%N`t5Wu_<`Pv*T9%z6&ak#ej$b4-S&Z7o>p07QJKGR0! zYsuIenLh@dB@PeQ7@MzUdgIFnfC3Kfe*w4=a1~%IzHKl$K3`jfiF9;6+6B-Lb?gEswsUQr<$k#SuT#yYYd?X0V7eW(&mjPXy3qngcyY+y5 z;0V222*OLiO@N2s{Q89n!o21A+H1h@uk*FvpxIEkP_qrH%~_SN?Saa?(O)PiX(&3g zGRPtFG9_Gxi~!>ScOrcT`nQXKp%^?^u?&>?0|W!i1`I`&Wo(Bg z0ps_h<)FV9q@VgbXw9gTDuT)dQLU%zgsR0D3>qw`tiBApQl61Of=J z^R;IXAR90kr^XZC`%^Rs1DG24Jw6Z67!&9($t*-Ed$Lo?k+R{7;~>c^M=N(`4AK^r?5ba zgysaC6cV7haKNT$wt`xq4F`<37ijr_)`#F5jP@V%2z7<_oc#wf1kC%hKnp>8eg@bA zFyQJFjsBHv%26&O4#X`+D1dQDawOqhBk3wxzO=MgibhLjf zU|YZpOQE)vVAVqHQEjyUjOvBj95{r`8im?(z^%0kwSVCc^4ftxC^GC&sJYe$qrQdO zvqs1;rBI89KZsdcsD(5`ysrzjqk!@I3N=6YgP22wS~B3Xyh6O{ z2?&j316rYh@Ku_&2PMw{OsIkMt2J#CUd#|R2 zHvr@PnwAUr?4YKFGz6cYHEkZCa9Gn^p}~wJ;1B41Tx+h)YYd4_A)pB&@_Ktw-VCe&up!&Jp;DC|X z@rULlB;Y>>^gO2kNFdC^zbm^lQ2EdlhaG+xyd|@CaY{fPN<<4vqc9k{2V98s^cF9B zx}r(&Khu{n(cJ~pWbaZd-`LooK}uQoU~~Y>ki^`#39}8t{5AU`+c*fLuoPIC#Zsn} zYlg`av^#^83SD9b zezT>vo>qtil9j^0X6*+n?MsgW?z$#l8^)prE7jQk!HU1j9?)v9Ww!<^W4%v#V!w3+PjyzldrWyZ1e2~?CBiDiW;U=caO#T&1Q6& z<`WI{vaTG4vZhX9=Y}akm9+l(T5o8}{1;js{;c>{q2^I1nCEb%vS%4+DY776>qABq z!_G`ps<6Jpl`8JhC-Suhln@t|e>EKSF?}+-IUF3LQ6KFP+3cosj0gT4T(S#Tr4h<_ z_h}eI*htFR^%)z1grg_1$0L-W?lVz%Qm?r_xlBRuCEN}6JrBhs0@~3?D4lFu0X^jF z0*z=Ag#_e!6tr8w&0p7JXFpd$#oiN{X_QhS@OVGNaC_>RQJc#{ zf|JV&vqg;K#Ho?Iwg!8Hu1KLJM{AXx*2Cue=KMG+75Y~?DBDW43 zHb!YyYbS_DR~ecAP?CT$$U#^x!nm-D>M*Y{N}XCX-Yc`(NYJMwK@1XvAk2!e>16h; z>#*DLN<=+!AJY&JooOWUdpFT?gvB9@Cld5TohZ>G1kC%^NOZY&aakzL)e~;Q5q78~ zjHC!g*z-sET4Qn{-__=g-o347)1*=zJQGFf2wS*VDbIeIqR1>RUNKk8g^pYF#-ssh z%_qPMf5ayPd?Jwt7c7h2idWiu=7W~-ok2_IG_R&!DE0GvjXaL|Q$0U!o#s4~be%;c zA-C#76+dxYJWCy?1O;A<&DZjgfw_N4W*5O^2}Z**pt&jNmLs{wsWrCMC(BWGPv}0r< zt!nB1vQ7fpbLJw&>=}pPIUX1YLQ1oZ9ZFED(S^J96O;;Uda6?1Gir2+5;9y_{qahL zN*kfiW8{}F)FLGa@%Rsce~RA0x=&Qblv)LR&&~p-r706j`C)K z%T`c!X0dCNl#VU}{Dtp6R&z4&7{U*-FM*fN1Ri{(KpVp%CMjiE-ejeb%QMiDE3ryb zl#X7$z@G;cXqU(ac7*614Lnpcap?$lYKjtM+4ph2wi1Gwf1*l4$ASMF70@*uDPUvc zlp3YVz^<3$;hQ)ms#HHbG(B3tp2jH=EOC-z_L_#c2aaM^L)CquI^__^c1=<&AH;yu zZwOT|`AJ1hn*YZyIjlr)nG)Aq%Qd~wZ;{?!RVRsfN52Gf zh{WRsyw9eg#B8x2*)?wv$q?%KhXq=1^r+_Rlu588O1r2%)fKA_WByZ>pq6`3&H`e} zN|@rtdg1l40u6&_G72yq!I_c{S|GzmQ}Z0Y)OF-fGvT<>WFH4=Kly%z)S_WuCOsw)0 z^w}q-DcxK`(c>i_XO*Wb)x!D#Up`*@Pc@M5n~bnc2zy_f7)S|A5SGJcPDiiv8_-C$ zce*lA4#oVgC-a}7Sb}1J`kuf{3{^ybWIRm~GZgd4q15~XYU-vneTLFN9QP^PHUlG{ zz)$r~-h2qt4g7`T{~}VEe=pDisIs@zV6SFi;PPTHt7B6vO$rC+YiOw$GV2MvfhS;A zxfKb@0H;67x*x>Z1X>)qgEnl2P3a|e9?UM;lz@sG!2``oF#oN$m^k2846TPSk3?ml zXDry!B)4oSM48RLOhnRdgV?!5C8**d48lq6=B9d5h$>jEg0P->%v3Bc;XrW#SlyXQ zHF*^9<*fHirJ>7upm~?sqM2y$&w0!Nr$tPEs0{dJS~c1dTjM z)zU2x77|1wrgF(jb9p$>Xx1xPsa1M8(BBd?ZHjJ#tCN+orB8yUOw_bgo%TCuUcZ6e zCJ6Nnn!I^kFngM;^md60#wy?g)+I$LA2bd4YcP64vfz*Ea0nP(d;nu6^YIL3+ERG) zbty{Spq3bz^+gP`hA8->*f~IRpB89Eq`0R+y0Mj;jUr#|%c5q(*xq7iT~Q zv{Dp#e<1tyE2W)(8RWXi5qYW}IU12S!B6?I6?2qM^1ncHnSGAZ!Ak+U>E8maI^3iA zY!%ijRq5%O9$O-8wmTQL;`lyrEfOLP)LD{t@?jNQ*|}6@k{pLNwv%<9t1NbT4YYPS zRybGr*ee8hC>BR(y~=#w$~vVfQ9+rIt`N!1xmNtbK=8i=5%ZHYEtrb(t5vU(t7%Gr z> z0sPB~?kshI668MyJ;P(F;t$~k@JAZSt&4$X25f}YnXCk}#|xCMG7ZwbSwx2NljjWt zx4;U^ci@@XA;f2a#uW+Elv38PAf?cubMN3%($ubZ!xpScw zN5ixqExKeE7D2L#U0LbHN>HmC=>KLz8uQoWfb{MmwgH;jQ1oSxnC3}RpsBc1jl^`y z+OJTXPpxOH!7*(yI1cK<4ufOh58yZm3C*AA9Ge2qM=IYzh1yr}hvp8Jmom!(XUK8ntfq`kgQgEF~uiOuHdgNvZ!kb+N^!^rvSJi{?>KDhx>pyJJS z6w;oB%~*<2(uiobcPZNbB1pnV0yj!h-9V}`=L@x!-bnSkLjI*)^;}d$Ym9zZfwj3I zdJ!XwNI1ywyM-Ek-PIh#O(%%WUxq=&pib=YG9~CkN_CP_J=L=SSHZgpxv)YFiTEEW z;59hqfc9yuA4WS0`9dpe&QLMiI+-fmF8w})sj;Z#N*j4S(2T5w%atsNeY^^peYr}RZ5y}QB(L@s zHi+^iFX5;t-|-SQN%BE2;i@F#1LJl{-sUA-lL;@7jO z_^GtK&rA5uO+JqN+~jp$!WB2U&{NpqUJWrHx(^hD#UAooPhkrQv%^CM^;d}WrzaPt zF)c_yn)9aCThJn3it;vpVXrw&+~6;~a*^No3nxpr$i`I5ho?gyX;X99 zN&k?IRw2V=S!EUeXC8C3varfkPPPiayUH0>A+5BeRu;CGmY-J^mb%G_0m52$IWIss z=`NoP5T3fr7XyTU%gDjQ-C9`e=z;kZZV0|CM@&&ICkwBubMlp z!V9lCVzyOy^nrX}aDcF>to$gzw77gVkXBcak^i3+Vv+ySit;>cA*?9pR2B*=$>5|_ zqCA)S6Mo#^=SF4Wioc9hPyNdy=Df;2NQH`_KW(LlNuFauc}>iHt+IeU$y9=DD|1Yy zwM%lRfKFG`D&o> zyN~a}K;iHQ%|SU_mSR3DD{rVG{NO8}sv`XCTkcX7p}<%EK2SJaUOpUXn&l_|9w;pE zEB8mBkXDJ}Kekz9WcH0h50?~qb)axpsdJ}_u(Gmzu!`_wWqDf_;c8`hMHS&yWjVcy zkR0GUvx;ynpgAaqtR(Jfs~b2xvr-1dB`s%i3qU~&MR}{_C_lI37HduNE>~(f-@6K{ zCGQ5SU4<;kd!egvMv{LAZk7+b3JYX8#T7Sa$Ztvs=`Ql)QbL}Ke5Vu{jGWF+ty5~) za@|a4-6kWC`6l_t1twv=$#QV1NystD`_U3^nk)<;LzJH`HVNOsfdCv4<^2HXMR_g2 zQ&Ij3AVrcNBj!3uz5uXCk`J#i36~`KJ~IgqAre5ES>6G#)-108IBb@`S!S{cSIlw> zR>ohMSuXOWo&rMzd@VlFw z4sg{?o(b^CP5vI)zjl)s0;IXis{xq1dK5hfRo-%Sez&a0kCP0=q&;GQx{9=iTjL8mQ_m)pU&==nFW<1UDk=Ft& z@sXGQpSG?AJc=Uu_arnVi;!%hY!-H411N|RvPd8x$`S$+c^Kq`2nw5n2nfXRPy;F( zKzWE@;vO^yTu2Z-4n#JfL{Cq0yaYWV0R@zYi3%tuxI7L4QT|n3HTh)z*7q^h{j2Kg z>gvbL^z;T`e|O4-z_vK$h7v>UcFNVj4mf29*vX(%&If+pDHlQc7Zc`b=`+K6?53H)0u6|F_x@e5TwHERVaOyuWz##Wovixa@A@;S_x#O+n4rtTT zJ9KVaJGtpK!z<<4stJ)TM4N$1{5m6cHNgH*W#z~ep*F72Y( z+Ai`qwC1fYt+2wHF0u~HTuZz4Td23BTTcWRr?+??RK7`<2%b-uyC8Qp-GjN+-R0Vq zFj{)ZcOmML9zi*8g(1GaSKB_=Q@#ed$_#l8gj@Q^UzQlgmzi4jeWqLv1yA+Wx$Avp z5#*Nildk|f*H42lJ|Jr$x9kDAY87;4e+@3ml2-s+n0W!D; z_`-qmb6^_>O3b}KP!@w~`5>KJF<91s`)3|1H`ar1zYLMcD*yD6fla;fh};UOjg+d`5M__aFMu6?Ol}1hdR$%t_Sxg|D8y~k zD0vRpjnT3c3KZpO(+i%E>p`V-oLmI#{5ZK6*sAd|h}p#xG`eA;j@UmZ%A?@-_KCWO zPfwJmA-8{$d>>}%$w_h-PS#1X2H9i{&dZm_A$KBQ{s3&_Q}Tbn-Y95>1@;%*Hyb8< z*_7^!ft{Mt@FEzyIOV|`z%EUb+k@a@&2$~p*Pm&J=)a!TMt2m-@4>a#XXxDenKA^j zn&)-ywIX8zMt}7jL+*doFn*kC$ipyH&b?^JFCn@s=Nq~uwQ!d>3HkLe8#>&ZfMXB8 z0~~v?>SZISXTvT4(BLP)(cmHAXz(cG7hg7<=fTj6iwucAE?i_duyxB98F5(d?||dv z+P2788il~;iwzxiTF7s#>}a&Pigzry@%|WNd=ewycZ+qg@`58?Y>SgSkTV1vi0x^M7!DyM9K*Rx*{37G}435POqK|7Zz zPR7YM;hG?qWQy~N@}o?#!FBt*zG6|5T#*TPspg+#iZ7avg7i*PZq5|PTglh@ii$S! zn@q9h4%8`aCr|VdTieMqV7WaaucuZUP|e)V?SfG02c7q0ZbKI|@^x2vEmOSJ4UNoC z$4ZZ-qXV0|qhr^*WAQCL+d=xjJ=;NgM=wlY^e;9bQltu z1LFmFQ%R}p@s8(ELpVE?6E!iw8x4UAD2MmQOT<(EM?Cvy;$CY*g0jMoyHh|#GpQG= zgM3?Nd5$H|g9l0=Z+_I4@{)IB;A63Gr^jU!Y8D+C?g>>y-L4kw^dtq>!lnq4W$AFj z&G{|x8jobj8_>=|eZJ%EH_NxtzEHjV3wWbPvdYhb2>mXfATHc@6CmQ0Zx@_?PU@l_ z-sKt9x<9syN}`{D|J_z%I}IMz(V9_OwclJVSUR7B7I$3rO5bcq3Di`zu;GWFmA&pEd>4!>mu+DG}3R3H~5(HeKiXTF%A^aP!NOdaRYFB00|?A`l&Ykm8`!E^r8Ji@T?Y9EclQO9YY~dCs^vR zg5|gg0rVX)v5@iS_Y#2L^^mNwQp*vt#>!W$|Cdim559ou`b7tr_gF!8F*S8FC?cI; ze8gvzUr9_n)QDPEW~%`Idt?KSdd_{|=B{}jaI}A!?Hu5U?rQ{{ih@1+$ufQhLORI> ztVJ6)c#y2V@2@Hjd0cKk*WaI{qB*QYXl|pb1F_>+4dITaD(bMOU9cBfd7rgkfV~^k z_WB7Q%avRGU)-B;tN(k!vWWVpz9s|KfLzLW%UZ%Gv;D1%zruJBKTROv$A2`mrdDSK zZJ`O#tuf&rF>b91qZvQMczY@)K4kni#z!(9e+$_eQAa=_u_r|y3&Jl@%Pw(?4>5j# z3%J_Qb zp}1a)ZMZeR${0`OYOHAyP!(Vrubik{A_{#G@RN$)Wd=!2x@yaqa^QdQD@}zVW!%!=`+1%$)Oo&7% zmV69~l{HXL9`mF$&%Q`%@ZhcKxm$&34c4=}s?DJ1ZbqXDcbk!(hwW1odmSp_IDB2s zcB>5Jfre`8aZkVI#SLlD<&nAw!5~kDwJI`P9XRgk1P_@}CxBg4olkh~ca-J`kj0Cl zD{AHmv~o$U2Rti%DBw}}AV5QfjfqoksvUlesi6rhSOQOY=vDX<;foo6CsgBbr5$H! zz)QYaBL%nZu~e;-a6C_fR0?fY-l<5A zY9W$p$xaO8u!TzP>`LxfebWghCXBIAw_Ba=QIP(l7EKNLZgm+i;nf#roiNAi4z_=g z@uF^I-@+rhY^TudWS1|a6^?@>QS>SKmc(Tr1{@+x#-%9;_@gvp`lwqzlk*vGzmAcY8lX#(0Q-Rn5wUf@tOr2oHT~A$PRv%N7@BATJW=H zUX8-%4#4%Oyhv?+f$_6w&26+HYuPsl9>-(0AXEcO>r$2$ClHKZm5|N?je@?b){hp%ODG6&8$md=NWLP2@6SVq0>s0Kbp}{f7nLg~}6Mux~Ou*5$kX zc5*Z9Ad7fv6sZ_+-MD^) z+>yov%p1k}`ZiwOyFrHL!nT1~r**o7>JnVO$J&#p@w@=yK_R3)fIFe}ex6M69Gb7O zlyO;?O}LY~a2*cyEofTFa5>$#N+>d~?93m0m2kZz(Vh&1;mHPUzzW$`Iy+ajoF6a%ox?k$Zmicua&o3Y;t+PR2 zztozSK@qF-8gf7yeP;OJ#po$cd7B!)<*p?b8c6TD&pG^4ChE!@XJS^a(jvqnR zVAyHegg8!niQg%8%IFcwg$RXxWGNg=rt`SONt7D!M}6UXYv?>&^YH3k)tU4Qu9Bj4 z%h{%N&gg5yP(`fE?YoCYN$O|hqqX#9p)@xaq}c8%?sco)5)1D|Ex>ckNY~k#wUH7} zuxQ+c?9|$pjkcjF@h+pUzCMoEtb?rS$8*R)IUKXOX%w@-7^+c!2?zNRz;U7K&;AFn z5YXjN2`orW;0vuDcg?7E3#hPY7AkkRd>!HG9i@@`sV?YbP5l5zn_;$D$oNt$<=zWY z?7bq}s5y#KBOzoocV+zve_NiAjlNGUmp2l9}RGeU^r&kra>7AjQJnS^HyKgYHm6e)P2H zsP7^Bs0le#LQLi&_67D-C>f^Iua?v{@VuefEnV)cdnvF*Y%`l}{uQOhM|cetI+J?; z0D9Uj_R>aNiCCY`f>}+fsn!*YoLyNvTm$nEDc#zpE?97FZT1G z2x1s%-Y=$j!<$Y&?$h>U4G$3^B|boS@gN#9v!e*#1h|g0xd&5VF@6Av@T4QsSxdt( zRPqJba?aAsJ+D9M3)a7d)ZyqNYUOTYaq%-`2hX`69RVD>Jlhu1bF5!5n5xIql1Ton zKaTMNH5;8-Pwd~s-~`o0crR{JgfTvG9Ko4t{RexZvn@Kjpv4W8NX*B>8J9Wpf$?^%DALA@R7Oqu~x0^ zoy4PZQ7f0&W@7t^ozu)02QOhX6sVba4hU&9fD1FYZ@0Xncrf<`~e@?XcanW+9IAF?R)P*l&{C8MnW&9R?ihjqv=% z-w`0S{uAN;G1ORorw}t$?$5Bfa|p!fh<#h3=_7=vw&WqrBR&i`Rs)}nw0Ucp*v@!W zDg_1)E+PHIcEXbEY-2l1hM^sy=3ntRjaoJPipOO(9!_ZU1979{`TydI8VF zbZVJ6$ol@DDF`zde`*Bj2W;=1vjE4}J^QG98E|knMHJ{?e!&54t~hlhwbuHSXKhbp zAg*uD<@KretdzSBQrP;kC~8I=NBmutdktcAOf&b-kCE+yvlMGQgo%`>{*79LG;>dW zoI_%J)+^Rx-x?MN&bQEoyOAximGSH=gkRNC_;HO&{>9_Un?8!HdU>{msR0T+7}sMmM}QhK4RrXI2e)Eo60 zA43X#@$y!G54KTjX&7BqIeL{v>~UhSNFlg|*cZeinz@^ep-PLnQdmeeJ)}y0g)*~< zl@f~(^Q-eH%OO@stc2KB&3p&PlBeMoJZX3ce3wU2@QyTeHTaV>q`|80H!wM#*mK0- z2gCqM=Qxg`9B!q2&q504tbNkV0vsb0aZtV1S^)vM0Z(;H#*?^;=jKAHU38v6xZtgR ztNR{Z3eVHN86d@uskL>?5-yePpw?NtCUA(zbPbAnl5BcYZgyoq<6$1=XV`}y0moXB z;GiWEtV)`$1FnayFL5Gi6tG4TYqSO&8*Sf(?Z31H-Udd}djOYRU@IF$9k*g>nN7M` zTR4i>r4h3MyaK{K$ecTgqjilO=*@my2b?^;dopQc+wNlzFm8`?zM73ME`QU^{T^sx zB;K=mvxl^PAQr3YuuL|wKWpZmpHD@rxu}<2J51s;AjU};$)nW|Pf#PZQ&XbA)+3s^ z$2~>f`}rBE5h;l|BtFXG;>)y*{e#6pRf9&}(ae3IfIG#uuhB^5Mnl9qPa#L!^SKMF zF9&L|@hq_rvE#%pYi16ZN|x;pdWC@N@TV=u6f`rQzfSYRl-L3|?kHvRjuKBk@r_l| zkZMQ+Xv3Yv`e^10PNNEI`3o#`v!;W9V>R9_H2(3|2}r+Dv0>AxSQ)>+!PM6@6L2gR zSWU(7=NL$(st)RQf6B$|w}F#dY&2HACCtf@Pm^)`8{l-n(Re{78ONV+A??z|jQ?t8 zHhhLkhw&$7K;MzFFrS4dL>%M3harV?DwS7+zN}Hfxc%O?OXW6%z||5n)OpCc(+bIm zeUB+mi;ZQ({;8RHij}i@)TL|B;O`H?1BC8YnNgoAuTNd5PxYP2dZvOD&YuWRf+Dt5 zV`*gl#2N($sQp%5anF&%_D!75fMZm{zmO@#4-XSmMI&hSE1LPPb7}j^=6;^TkVv(0 z*NE1tJO-k)4nm8@ixcUdPPFB{BXz1SB&^mDaLx>n1q~aO#>8D`kGlx~T`L zv0iNfCWWPu+pdUfv2EVm3pjo(2=K=O>yykQtRH}xi*z3k#qSxnKXaIBhy%jfeKt9r z&5l@+8l%O=Y|=UaS{VFPesk%qtALWK4veI&nnS*p-A#2{&!CxesaX68at43?gES3s z{S3O#N(Fy_l#Z%xFEZ*y!Ue~n2bmBp7%y|(T<5<4M_28;<@;Gb0Dt`!$+``jFX;ee zi18eO_FO?42}CjDMT}1dT+jLTWXNi)TjkyYV+ejjj%+@$*NL6hO#XR3x7!Rt3XRym zeXOuFWJP_d{5oMkvkkypy5B#Ld)>?G)M(pGIb!0S>A;cpI8=c z+W|KK$8De@K4}$0W(16yCeXSkHCq;Ej;ovzXMQXzN8V<(G2#aLIzKz%i3x-Ara$}C z)QQv7y|U*o^r_xU%*4tQ9n4kHq4c3` zDr-{AbazVXaHzO{-lT%OsXpJ(yy-)y=jM;iojSJf;Gv^^X(-GdKcgPp+TYw_s^^?$ zhsw@Rm~S{L8&5F-lZ+X7T zSZ#K7S_kzkK3**ZHK%p@(Bj!@?`kt>L{wH8NaHK0o9ek*SZ4Nu+s$5(CW!6aiOg@C zsvPBJio^Ph59j(a%FTXou5V#E81v@v(!~57wHM$7>!_c_-|MCvYs{2{;$@_6@q?bq z2iKS%8Bx^@m1C_rs|o(0BBWOEZM|?+Ug&t zEefuYdfy;EiSlCLA1rS2S>@G>Wp(x9#eX)h+-+H?sCHYX)L_jk@5qwK9a+lrtPM+4 z=CZpH8EIhx`t0>o1xb8LdDr+$;Fa{6{TkoD_Ep1w$GCqx*}BPs$kWS|S>YgZet4e=L= zzb5#L!e4XzMdL39fBL7TR&I@JtX6J=YdieK;V&M43Ha;C455ZZ6guOtEB^G)b0~Lb z$_8T{N3sTf-Ur9d2|q$BzocD9Yu7Qj zj@8PqFoUwu7~~j_`a}&j3D*q#O~GFl{-)#4_w%||pNZ?}M+M)#`*v{osL(zq3ilUv z`k~RWJ0G9iJ*@GTb(KE~%h)#loz2ZcZ*=N?(D421c_V6OR<&Mwa%A++6XzT){jz7# z!Nb>%h4gBev)++-u3F!7mg944Fa50L_I0bnXRKM=VNc(b%-;i-SMAa&eQhes{CnRC zCAj?RU9Fy!`>CkYxNp~0?r`_vm`~>KaWsi))ird;`!n{A`R3e&;1*psTp87GPt!Up zgF-(Yxbal0-{0BZW^}cJmoLuTT>i$PZHrqS`?BTschAl_5xP9M{GPQxY#y-BF)rt~ zCmYT^dL_I5<+axSZIN0~hZcS8U$ezx|*G@5dgC-G8R-=M$!eR_k*A&XGe4#x06@{nIZl9~;*6 z-G4XKITU*7N#L9hkJ%8{#s+{$=Ft-vD9ITuTu&^R!Zbggf zd>ezI2KZ{SDhdm-uuNsK*}`5@&Vu6;Wp`Bzi%?jog>6)ls#{FEI%(9VhI)w|Q;zsq zlzhKn)>L7YEXsV8zEq9`T3DJ=-Os{Y%7&U27N@KXx3D)AR>NY7i!m6gi#9t_o%I&f zZRp$Nugf(J)=TWJa-$OI5rgmH;`@E2cZkK**-NoPi9nA|DRV1BLPfntuPIZ|``Jno zT5hRCK#S?b$0{l#(8qSvf7YKYq%K+!US8?y7s$R5EQ!k5$`)2rSy`n8`%F0kAz`8u zU6kHnsipJ|v#?8oGMYNi4k#mFs8IrYURew^mx_iQLh%-Y-X)srp(dRM^Dbf8J?hG{ zVHQ)2*9G~4aiG3|JT}y$%Mk*U%y=$V)E6Nlqy<94jbxO$HsRtgjW!o)?0? z5G`1Q3$BR{&Ji5K(TP z?ki;kGUQCkOeU+>MAbyhaT*p%WVK+{mNF=_itrB*d3m9T-Z%jnDKbK1K{Hd>X|Tu+ ztfT0hQ*`c>P;H1{_(}xYPLbTI33GiZe6n67$cLhFBsUC!z2rwzkyqUaVT>uFspDdN zRu;kchLD>tz7s^3_KNajk;WSc7Y-J~rbrmSAMu(_c;$X1C?1NOu$=}iYfO5XMtUit zMK3-h)3f^`(^$n2JE`=>)YL(CI6-8A8^YcfWspx2=ISMAKO~t74-ZDZqYM*D`PtOk z+r|)u*({DhSPRy}g3#K{DAq0Qwbe@k7Mc-;U_1^w||9{b-%OnWPUs zBI(mK_$ge8KK-EtjMLypK@WHhLq;VjsG)`!q)cgOiLu5?aghh5xNHquv9_izEgJFp zrJO|ERYo+j#Gb>VmXuEY^=YM7m6u$pwA{p}on$hshcW8W{2Ef;Dk%(_HhQcC6C>t7BMpQIQ z1I>S?Up=)bDn2YV(H)ghRZ26ImzuQHG+Bb^CC&3S&97@coueFSXu+1|Mk5QGr&O%iVt6O^e5itZ&F*7ubk{U6SIq``|dr^09A)7T^% z&NfQtX)$8xRz-vR1_9bPtU-IE=^{R!=8{Tl@eS*{xT<;c7y1 zc<82tW|JB#ulKd6&0h)k-&A4X(aP%W`r)lBj_BL1SKrpdHys-hXHrcq!dt1?^TR8d z`t$%$i5^``$r#>9wPs^e8a=v#+Ot`BC3Sd@@Vc93yxhFJ^7;5s<@@pTtCus#kpSn* zk1}GyR8~&;bwV<}LnjtE${EPw@{bve23aRaMf@4@N0w*!XF$m)AhIUENi3BJMCBQ{s-}yi>#mOSbk7PkQX9UG%u>amB%y*2 zGn6-+((p7;mM&g~>B-;lei8;728J|pg_(6X}OfJX0hG)BFW;Sa5zA@CIp=e7FlN7g|>li^mn2KaT|c;v|P z2G&^$ogx^@8LDda%*IPFVvUAS)aetTx%0M)&2~8n{p(> zVr-YDT*_z?Lg%l#si$j%q(eQW*%V6%PEV2W|IRQUGj(PrLdQLhW8tu1vASHbF_(D$R%27ry+A%!9NV>P@XE5wF$^d4YszpVdAT zQsT0)lSC|tMsU>hm3fnDu`J>Y}=QTYnkvp(44KG+iFFJLuy3z~ppsTrwqK=Gey z36V3E6p*dC4?$_LDG9*(o;&Na9bv~P6M-cU>7Uiw&V{gTloh~|hxCuWts-ogatPP~ zK3IKKM%bRpV_*|~u=;L;uu)30OzB-+vc8ZdY-eR?rp2Gm$MsLDayHYVEYGYOQricr z&u+vsSt)?T7$2-Y%Mf;&as}9QAFMw05_Y^2o@EKqwq~M9eLG0lI!aGq_0x1h>&t(_ zwpV5Y+tf$0zUd)s3*{?dqkXW~wY39bBb2{@o#2DjCoaOyQ2eJ^LK^#Ei?wNuu-%jd zVEg)D_1z<38z>Wj?c#%7q^(y8+eujgtbTt30Pl=X*jJT9(=2S_rt{P08Clq-iLdu! zENWB1jJM0NKAU>ZxoA{U=2rF3|5HXFO;J;oo^x@sylM2@Ux3U7@?;rusnRpo!rs|5 zI=6_iFO+6)TG*GHy1n^}G2{noS^FgZRmSntre;pFk^QYCxc*?5m7s;)*>z>;!nfJo zO;;Aim)q21QChW)`Q@uuy;<7eo#tT%bKR~6!=``@#Q{t91XkZ_Fr+vy^48n2A9-8IW*<>}LvVS60)9k1zt-%%>rmEye1$4?`e>2kF& zT!OAF*;^Y&%%OYhhP?q2Pp{I_QoHk7ihGnTgXaT6O)Y;-8L+npJE?rUw^2wJVsz%( z4x@v7*`w0ZWLI}?cg239{JpnPSQoRz(!C_U|9)wyCrL`=aal@(?`_rh-b4c~Q?6(} zJg-`qdZacErZc{;+4BcYaw6t-o&sJd!n@umE#>Ab_ZoeKd*La6kY39<@BnHl2@GYV1p|RJk%)z`sgmW#+yn>~rO_ea+y; z-}ZII8FLcTG*=OVi}d= zOs0unCXvpP6lW=~o`e>`7HoI^#W#~CJJ8q+(byT1l8^qE{BCzAycPy!mXx4YR3`3B z<}&^vq?Nqw3p4QrvW1clNW`HY%uupK5@2ZqRiVQ;N#U7J@lnFl(M7eaJii6nyK~D%y z?3p_R`4;{)k$;WO=7plO`EVhOF*bxOpHKdI>l*OOsMHU$2eJF{8EDn>8gwOaf*1S} zfzw6jq{`;p7g6KmOG+K3o>YO@Y0DH?D!W>UaH2e>VmoK4x(p(d{iJwF_OV*MPvbB~;n|;)I!16U1X|qAVbXIe2 zCUxio06nizf7}VFh#NlMQwHcnfENLP9qR?dj^^Cd(pYJ$u82=h7ceH}%myMa9>s3X z(FRY;GFT%jI)@rObxM_(>p>1E5$>y)JJ+_J6pSkZrkqzjcUKA;f?cDw(c5%8U>Sg! z^LAi(dgu!}IV?h_uTUfRtwiK_@(JaZJ?C|?cPI0HPO{w&8m}u7r0b&*Ip*A{pr+_C z=Z!;&r(Eu14#G_+$G=6wBx}>oRF8*Pq54kS zbY0h z{?3WA{d2f_z7fES{0~&fV6+6W$9J$n&bf=ynq&C_ft+Qt^Yz3tghVbohp)NR`ly|f zl}wl-H24yn|nC5s#+xYqfUxVu?_uYfKo;QL9N^Arog&^-T1sPGaQjIR;1 zcV7l=PL}2*}MH15*C*>UIkvX?Dg<%DNJxw%f!U@#h2mhk}s;d1-_nh~A-` zNagq2$~LL|wk!uwIfu%w9bCkXoXS#3gloqE4Mg))f&|eMl3BQ!Th@HLNRWKhI{(>xLP}wM4Qjq$P z%FB|Kt4D%^&yuBF1<`;}=;c+0AdKTrl{!al-O`243j&CFlvoB9Tt}P z2J`5b5${Dbg52;R4H@nRnWr3vt8S~EV*OEI(7KTOBaNPmXEAyTsq`004$oyVW(v|D zV;GB3Qv`5N=WX;o8!&r(K`?p==dJ@Bz(uG*{oRj|iQNru;$nB^1)$Xw=ciW68h6D? zs34ncGgEl0AfE)qoiXQC#{n0-mrgQV1Fg5XNfkz-*n2YDR^?gtd0Bo)wfQX{tx z@x&8PAWCIC8cT#=*%AQVXp``91H^5KRyjXPj4`bdV$c>qmrp~STmY5wU84*RL&@>~ zNIn3fXO&q(CRj(@^HKT_%RB#rWjL|SB9{LDi)AFSgg(>fro@v>JoO$bkB`>wRDoEX zziAPVqN`(pe?XUc(fP3Si;j_O1sY*5&Vz@c;Qc0~0u~;ogl#Hof#!oODPC)X!!wZp-Wb>7)gX8ZGJxYjD$Z=g4bOj!+MJt zd9RJ2g)-t*EFh(XsU#r_gN=Uy2G2TlhJQq*V^n&FN{^}JqLNVjS$(DegFd99ySj}W zU>J->JmC;bEjCBX=!gg|BU(gR=zm8Jb`fZoQ1)DweL>@o668Y-?V!qPFrr}t`Aeo)m}$$O0%(;$O059q z|Ec_SGB}vlw_r$=I4!eI`Lk55et}sm10^{=6?NeJNJ z`(kA$qcgsMGATIEosi)j_@l%YN?yvOS+A@4$g#os5>qTOl-$7Q0^iS&YMCOjKDi3m zAt#iGzXBc40q3cUgDBqN1eWL7=#>whIk!BaB7pKdxGfDD7)1s};g4k`#Z7Z1;c^K&Y~3Oy<|+Qj=YaB^7vV-#Q)=fwGaoORdz~qfGU9$FUS(# z;&wE~1w|Mx>uJ1B6HCKqTr)y&Jr#){?QyO&h+0UOEs&$kc@?0Km|DZ7plpdGPnq+K zgv8Vud`+&9@+FcSWzIW|s8o|Kuv$U8CALsv<&?LbCf8s^Vu~e(9A(a1MtoDqjiV*j z#{sZv>K`(jIobg0G2epXP5(fNvP-h7lRc+U+kw;q6lMj$3Ils$f#*h|yhWvZ$50AJ ze&JWC)PYLpsFaS9zU)$p$>dKjQFnoemT-=FzY@}SjhYq0_ke@1AUWTXlNBocMZw`b zBNls024jnNSeM^g$S+&gb;c%`4=0{>RO(Nq^XMTB+Y#jc97kkny%sgE|3IZ_I(G$4jc`#04YhN%wy0W*fb0W{@_Jvl|2$B(&z=iJZHqI zZz(@PmHV)$u16~A@y`+Hu}UKufMX1gipqcV*y;F9Qv^*N9tAR|#?zO?j?yY)$nuk= z0PpI3IO_7Gt3OJ-&ndLnLt_Xc4>XcW`2@Z>w+WGUN24AqN_Lmy>BK}w*}O5KjVLAM zbTnjDbal0bB{?h57A@5-b_9N;wDT{qk;6`pjv{YU7-MsG1*k>40>}ifQmS{y)*nmR z1aYvB7apM|gO1SAhdZ{$Ra_k4X#yU}k|5YE4Y&BzCiB zAgcj^#kN#C)(h0=s(R_ljy3Ng>~wR`5gffSHy3xF+A2*Ty873fC98t#qUE92P08Mgq7JyT_QNJon|8DF^7IHe+ z_;qq2kapgtrgUa=sKOglOXLu(3#dG0m1Wbnl485^$lYRARK;L16&o{PF@EazOECZk1|#M|9n zwArp70dn>xdM;um2_d7d2=Sw@C_kNx#hVK3e2}B?Cm4OrapZ{7^^_;Yh@s=PKYo@& z^A{o23og{a+nxr0p@COE4PK&w7d#D~sez~df@t+=bCd=j@-%r*4czT%a2pNW{AqAq z4QzQD?5BYZ0O!OTvdVRJ*0(#Azzek;rw)-8J8gxO=+5*ZgOgLv`;obJ+N@frjfGV< zXru-K+i9CGN5^|Q7_Q|jgoK?o5kT?s76VwPX*7p5*5i_O_#umIeZ2;!lXH;U4=IHg zf*dg#SB8eAgFs+wYv5pNFkEY}kOB)0Ql0?Kor5HJvn`*%ZrsTv+9^ZH%el6DkV8jo z7~y`Byokt=b#`f@MYlsS#HinEgsh#mL{dX!)OQamlP?C3b7+X`LO+Z_b8a7uSpG8L z9y^U)3Mp>)$54Ka7Fl(Ekcs0t5bzOL&5((GxC4p1F>zN$Nnb%6|6RF$v6jOCIL#M+ zc(6uf0qPo5q?~#VkxVe^J;CU>^{{|ZE;)vYT(m^}1~whojT$zXAFnE1O|~a2b$Kaa zks%kNO}gGXQ0fr9vGPkW5t1LJwKE5(RXXA(W6EqlSmW%gaqa*O?qfj41}g2K(&tp# zK&2H_`W!h}9K6WeuOULS0s|}{)3~1iOenCDMdJ(ZVL(I0e}AOL3lb&px&)qBW>4ER> zi73W^$1|7){%$2;P$|R!3Yw&Wts3~hcwZO0EXW7b+r|1C}9Rl#HgOfE(S- z*05vExr->|UjT*YO_VB-dK55$3A8E)j;EkJ<1VYpBcvnW@ykma9K?Xh_uh65MLFLO8P(fw0vv{4fIy7UawWI{oYcw zcX4Q-qrOHZA_?PXI!MeK?68(qGXQ%?;Q=2c@`&=(ee6#(EalC=G;A8hbRu~eHvxIu zLdlcLn`tFGuTLc?xdv@OStGBhd~l;)%=KLetVd!1UE}{y<(gJGMisgTOQdNIY(s5z+K-FopSfzrhRDTnBu&OMWNl<)fT)T@66eqm-yccaYX=Q zq|x?&6I@Q~#=+CD`b7g>;CEUDlaizCt)$jjgY0v^FJ7%=-KuBYQmDLpE6jo6=}9Xk zXC!>^JQOX0g1k?GT$kbu!_yz@8|^&9(;nq9&HqPC&A`5k9~ARq!W9oJ>JDmni7v6} zgtFnMNwt zZU;H~X*7tN{)Ba!2GFI*)K^3B3$Q#dsL)4?=TGn$DOe8ZP^ak!qIQ~o zq)U;hNJH@Vgsj+45J}`x*ARN@(H(o{1){#jXW`&8=7$vL-{?w!kZ_gT#foLtQx7F{ zg}o?m(Q^vgemRCf?x2x$)ZmW&6_E)UDOH()H#2Vg zDoH<4(!Z+HH>2LTP0a;SP%%HZ7q`+`Y^ooQ2e)a$aF(rP5+^-E1<w$san$B7-E}F0Eju4jO1vgXS0NIHa;8(8cqX285wU3E7uN%?(xPq>#f@= zF`wg#RGitir}I|H0nt1)x@c>udM(}t#}i~wVIsv{;bi@NTz zu~H*zlKHz#TNmn4C=CqES~-Y8{si{pl`uV!5zlT>W{4gQ?>{GKPCa#!5ep33zoLh^+-ZcdCBQ~eqHd8C7p-dE*?9M%W6VbU%VWL{z zwjHxD_2EUd11b~1d=ZhjO!tccQtXeKhoR6d<_^uC7TiSz1HZLXYCmMBvgDDS6)Ptn zgoUqp1` z$*h`$gl~3id#4q9&e9hw|M6SL&F?H?FI4`JVgaNTw!Ony%s`nS!%v~1)$q3NC3*+S ztF{@YkZRvPDb=1$fuZTzT#EP;C_b7*xJ*BvR5KWBR*gU>#egs3UAC%g7;9{tzfL{I zSPSF8b!tT;i#9e`r^ewr;!jAX`M1miyVt-2zerbYA+*<3pHr=ja5)i%K8Bax`U+oh z_aGj1|;=Q>es)o-5uVJ_tawS*FS=5 z%D3uYYYJp*%}40~hlHroD%IL9~CHI=?)7)oA=$eN>(;Hg;O8zHMT4 zUuY{dpZ^C)YLY`-@jMh)=YI6(Re~1440Svp7$KpJLAl->d%f`WF z%+Una!ljy~LKt8vv?QlZ@h+0&&a~O=J)GCDaJTUn&^2AsFKxV?xd`9tk|g*V{}nJ2 zvI9OzabAEPkdVq3ZlpXNqDEC@fyVGJ)uf87UBFa9do#uPgc5V?SE{oji!d5Ds%tB< z@SysH#p_t9DbAaAv5VlvYt_>gnXUepA_g*Tk)EZ<3HH3BnRV?s512Xk2HC`Um5=*c zZQ#e6wj2z?q?~=MYup4|Rde3shoH{c>*t9_!CcqC(*_YQ4%TvD8+Bkv=@z9_XywZPFbRV#$jMhkk_@)8IV}z}+Y#uDAcH=2l`2 z>JsJ`F^G$JTM;|BGp8RhR#>ebsDuGI`g8SuB@EE^pR2aYEWYPopCY7>)7P)`H3wh% z;`CkQ7rp$MPx(Ec@$+&5d(y`2^O^ReOLFc{dXS0A~P6IYo>%sjET33n@vvOffVz zTtO}OsB5dT@J1M!L=k|z$nOfJuwg|E#T@0^z90siQ1K_L)azAQduwMB;WkwPQ_K%B zcXURvA9I-&?pB}oXH9~4Lu8S>g^6|{{*2vOj(@yHUFgq(*-rISf7YhbTx!d0>a#;V z=g+!5SC0IPWm+l?Ilq{rVvOSuh`+d+lo&z?-0yQu_oL^Sb1#!zcWi?~Ex`nCMR7 zeyWZzGh3TRpe1e6JpUqBi-jPsN&I8Vg1j8nBeBZUg8ttx)E#CP5=xHuB#3rkY&rs< zbtr7Q?lbk8nMIht(-a@I4T`t;O065fni^w1ReJ`o_z_)KQW(xL%|iEJqr7j)WB+mg zBw(L)e`RojqZP!%{a)ASU<|_bw?rHT-7X;4hnd^%^6~xlFVw*5tY`Zku(v0mtVi)w zr^l;h54|>f=@V%k#0s*`MPC0C_5JG1YP|8eT2P(EIHE}Pgs}(Fy%l((F&K#N=$B2Q z$r%FF{fs9X0V8WxyP?((HX;A%xtoG9j8-uVl4Z6LFXkvDuLnS=V^#=jvNQtiE-}=R$riMrq8^m^-BJ80S)3uvkNefBKDjB#6CG z$)7^XZJM-2jjY8QvTbUwT5MpYZ=`PXHmd7tu~p_cY5{6s({Pm^T&a%4?`j(ReYEwG zh1F(8zh!EL5H_Py%5ovff1~OQVfFg2lYy?^_N4m})rbOeBGF>YEoFF~2QB35$l*&i z(lF9a|7DvWlrMzcz|--YWwn{5_Lh7SQ}%`uY$U#`vSKL3quk&dzXk4s6}oi_1qo4-mG(}2w&0Bk<7!LfpHCE^+0HIlke2QRmT zKiRAvuFY!K)_NfP@8e+p<40=wP}a_9U8Z&nWnUR%RP{pHdfr1~6WfXM{H?|6`Y>j7ECzT1z!*Wjtr$VG-o-c=sFV%R(SQOu3Q3>;0^Rk2 z`KB5y2mHH8(OklJ1h|hr(6}D~1mC#~Uq!-;m@zzEk?DBk z5=as)JKV8vN>O>lc^$;t)1>Bs5u%BS1V0WqIx|9&zDOVwsjq3@Q^GqF{3{ZnX&+-1 zBAO8V9fE7x*O&A)3PbA|_-r7)8z|LhMA<=8e-#kC^c{6_9ah^>2a!te+r!2Oc7doB ziPJP4h-P%;8ba10q?UN!^Wl7pkoOS@y5e(vkW&bGijbQ2>2=G*w(m#SU4+&8(9?&N zCK~=Rkl*!?{b&e){CR*O%hk?xS<{4S?+Kqs;1u*wmM&swcpAbdvbuT^O~g3VCNcUi z3~XAguBppfI&$DdnK1Wy`udc&`IKpX)M<)+;MqRqk>2t?&l7KXugB~y7kN5)B`da4dRFSLw3%^#YMX)wj zKq*sC$M_e$EtkgWnB)jz7P308RYygzCjNC0so23%idIzh{Rn1lvEh9|F#`f9*HZGJ zpDsY&xb~HtDk$})W6OhQ#m;@DUP5c^D>b4X3#oJyfdT0+tx>zwV~y%{#^~23fUShV zdNoyKf6N)QTpjtoy09Lr!(8f`dTfcY(^9oleHL7)HdIIQpYyJoUZ2%5zVMcsU7v;f ze+e+MRyx-2x7Mm()@OBVDK2Vnr|lm4&X2i8<8{}lXCS54XbN+eY5y9@mIiJ2tikVH zeqYPxHd)qE8(Pm`ruh&+AO4o?!SFBC?lxv~+*lwR;FM=uQv>J&?$XF)DK<0JkrLY!{5%!hHsnYen%#+n%I3)NZ;SVpA_ z(s%2=RNrpEY6W~oewTAG`uXi=>XruZJD?=xok*bZZFr#d^5O*4AjTW?3Q z%FGzYpr^wvtSuZEOBqE z??ka!qw!7kU=&n5m#1Ee!UDO%JT zW8zL|2!P#{Dz<712#$%%9lO;*;&v<)qQ9c@FLU)QQ{-t57wOBmc%SlP#EOI$d8T>G zxL4w(+3R`iQ+D{2=XmLhJi*IKhkF~S6IpXK;+v>&UIN#d$wi?m`@zrOZy08W7Xzc7z54K8)`7mGz#w_J5xEVD;EM7(;cKhj0e`Z1d#PkYkm(McHD8~oi2d^wGI=e6&~LjR$j2d|+|>K|=z1oGVsHJ~kqZvG6l zd0W=W*y#;*a$95-vvxf*SN)|et7km<`qqEjvT{b_g<0yoIBXzqWp1tAp0#7f8Pn8$ z@l2^u4*uRSO}!G&W*Mi>P{(&*GmMR1-FmSD8_kT_Q`HwbvTS3u>FVK*Y)%COh@YRT z_UptNwwVmo#Nm9FKg~yd?;-An%>odk-jBC_70**#(}pI$Kz##IovG^jPE0kvGfhoS zM2I9!Q&%LiBxCbQTZOWk z=X7WNjFl&=zjbHZjEi1T-?Fn10DgTm zXscwX|MXz>f{IYVNu;&peLjn<1CwqZqt;Gg^NsCaQCFp~v4I9ifL~I`aE>}DSo?oH zO11W6jf~yKsmVQA!wNT{T;tJdR!=0AY7^AMJz007>E*5XJ-a|=T=$CFq8C!!{70yi;=-w~E576t^!>%l5T8d%2MkwF zr?O_oq~R)l!)=Ih(+G8ZZ&o{?B6Wg}`M?kdO`%vK&v|rOC(LngEjG#PahRH&eT=%+{1zFLI--VdD)~2J?T@$yC}e z@VH`k&O@3nw7c>6DQz7ady|&2POZ5_^GPCMt|1Q zXdkYA)1TFKG#Xx7npc>$X?ql_QyHW3r+}%itXf7&1o#8GKn>>yUvFUQd_36*bYIy@}>*FHajsN zt;IL{5f^jbn-B5hOfly?ou6n2u(XAv#&@KtpQK@c%}i7ONnjyDQr98OP9%p)Uo_d(76R8?y8a7Y8K8Q7{G*nh!n5SA_ zWL>*+M2YzuQv{&7g_#qx6KX+2EEB{N?*27U$+V+$yTv9gCxPbzd(&=iQkWTtkiKcI zj!eSK4OZ8@$l5u+coQ}%4`bs&iyRnV)K~R~&D;rY!rg=WJ;-LI{B%F5I2{9yMY0|v zeiI~VV6yXqEp-#d<)|G``^nX_25B`KUGkO)=;-c(zK#*v*!(#>+(tsNPraL)L5FE*K_tB{x|EmwA(apAN{Efk4B+^(e zTbDio5kjynLMs;sgym>AnUi37gW|9VzcWUCmp|;ZnT8)pD&>Qy{hWjwb3rAMmbB7R z_4RkLBL8Qw`u;E$;^2L$8+5c;)>v0GMlkV9b=tz%Dqy)bx*P0$gv*>4MvBb+{s5qZ z@qA9w(4=8W!}X_z`1rvH6+D|m*2$%Z$i)f*4P6pHe|N6rFNa*pcPS&x4AzOR5>e(q znt&`W3=R95^F~3GhkhB!`*>1pi+^PNG{)$m_&G+taBmThg=3-aw~b;6K?K+7A&Z@J z{&*QpW8~Kib&E&5C9aEm`K#{X$OwpWn2fc&x>e=DA zwcL|#&eA& zp$yq(dJ5fv?iqJ0E3l-MScQ>n;s7i&OiFWPUK8Rxd@}}~hRnihhgkL4{h z-pxlaIDOI0+nHeW9DA(qNcecFZ!D`1Mjf%*8exZ6&3gb@L~sixjk9RxOG~{7)po(1lNuu2S|o)1YZyMcMlLu=t64(Oh)>{M9BXDg14lv z1dLa{`h~JdCheuN@*tn`7?d4yCfe(H(~H>adCObI7TTx0+*{u3>F!f*^a(?7LZ`Y2$9v06+1(huwKdo%#}MJdsvO%>4GZ=%Aj{MeJhg$cB-Sk0?_+?OCdDI4c| zSmo2>&e}72?u4o&pgT>9h~jlLbg-4k*(M|5t=}<@x7U#^{(Z7GejHEu%AIg*I@m^_ zU2^FOuw#hVz<{9XXb9kJA=g!T}jgf$Od#Id{7OIMiLK@YtqWzVL*yaSQwOI8=6oKEVa8^w@|nQrV1 zG1HNTZ$YGfM0Z<`=PIPZGRW4)`ArG`_cg%hP@7oNU=%>vVgijP(rTnE?(F&yz`K z*&Ken=r9%k?~!To5dQx+GH-LD@Q%y@BDiQLBu3^utto9}PS>im)-mTgp2O5b^P@Sh z14=xe4A&AR&2aD9?_$-q-%|^tL@e^~gMZ27lx||v^fTs)$`k~yL>yEcHs|&L9r8=* zVe@y_JsnYza%h>iNaK?X?x1uqBROe|(OBGg8SA5>GhXCrg0Z|!XN)99ozD-tBG6=m z54|4eQ!%4^Uh&ou;*>l12M9cxj+=lDumlGI+u21Wg31et&!0^3YIl4U(APG6>2vG; z-^3KUFAKEMDS&I!bDI+a{uRN40Y}KKl%($ws2jxUBHR-G2EiRydH|tK&+HE&;}t^u zPH=5{en~R)A$S4c-_@ZkgB}rJ7RCsL{5c?aC;ECGxk}&u4IENd9_3U1QY$;?w%j-$ z#73WT6Q6QFpYkm%@AL*%`oKr}lw0|f$M}?e+sYhLs!kk_K}avKi%r~9TQzzmJ*H3| zY+%aXi~LSgW;Ab1_Qg&FKM#yt@Q{q*ye5vn&0}bOh%Ls2mqRY->6(`<(BdGyNIYwB z5&&1CUrr%&cK7Q^!QhBP3@7D`#VE)<3T(1-7je0|`+{>_EG;OrAyMlQb+QkIf)nzTh$ROR$(3y#eGI#tCTRU@ZGBt-0lyk41Ik#qI{PZ1; zWXjVIGv71^`0qm`jWM^_ZO(ZKlK>{2S<^ykcir?j%{&vt%rg$@8XEc2)tvi2V3>4H zU_$7WNeE2Y?c}Dd7}22}GzE2o0yzocL?Mw~kP7JFC zi|B%-`)bh{5{^>&!0J{y3oE29f{SvqYI?1lwRSLpiwO)ijw^kzx43Rl7f-|v zY-CRvu|JXna4kkiY`~-@= zR-}llry=J)qOUe8+d-549lC;a%=XyhZkp%OD~x$RWR<5M1|L`0c*xs(OsU)In06m9 zCPWT-+h~6C2F<$Op^0BQLp0`!ACd4`&>f@O=ySiP(e1NWE_*xfrg_M2#COnCExzsM zF54e=qAiqo+SZ-$=vBCSAkse#!t6&-(4BCPVE-nG@+m5JN6yPmI07LwB92T|`)Ax%Bx-p!l64-y1(|3A6_weZ|qRm>iCuW+>uo1SRG+xwtfW7neqKMPFQ=riG^W z1&~OZPr*vln|MqY)8zKZeq?udY}gT@#lDGXG8M9E1#$ok=rx1xG@#>5w3NJw8d{|^ z<%+$EiaD2lE=F5Q<`I9kT?C*b9SpiEuRo=V3o4K*|5DiIB+Q%)ndaPt{+$elc#Qx!*?Bz0>5(@LXxrd_1Eek`_PW`D926ydJ>M-#^)VUQ@G zMd!-wVFC&45mNlDJxX5@_Bel7x5u3`)bZFq03bUwlGP)qQvZWdeYXGQugk7xW5V#> z4lVBF(|_C|rG#)$z^K#ObI&_8Kso^^jeIEpvXhgbnNKG>kp}2w_qRnK?Z7_M$9jhy zqLXdTP$y~Yq&q!KcGBqWWKEEulLVknc0DbscYl$cj79a?PDWhQJ6YDp#~q*PqXS*= z2%t|Vk81#LCyN9?cG5NOsZI_d4baI^Z;4Kh2KJdwb^-+)+4uCbeT)OG1Cd=91TwOt zL4!^bfI2ziFHsGlCg90Fs6N}tj#vNN$=X8OvS%g9krf2Yr;oQ2h;fz!H{;2Z=G?9i zu;42O)YBd%q#kN=J&p9w?ua`7gerNcJhP&I8*5{+qQA(a!B5*PeSvM*L#=2F^Kzg= zx8wr*4jO?RM_2OsMSib?WW<*I(C%lq0%Ls{2csetNG=jfGDMBRbL)0lHqsVdp2Gr` zXz-;g0t~7DTjUfT*ac@wG#_k&E&y&J;QDw`ewWJSsl&_2F6||B(jnYmoJ5v$C%jDM zk+M9P$`#s!a5uhy>_&jwaR3;=$sYo$FLV1~{jQgX_jZ(3+WR2h@F{=jQ=a2f?%`98 z@+r^vDZ9PpBF}1{@_N1Oz@mK*c6qu+vwh0%`jlVyDeu&o!Mn_-eAuUa#;2U-Q(o#* zehisudc)rXv8Zf97ht#P_ufA5S>c^WXGLyAq}a8e;&e&Xbc*YfMFeoI znXm4i!5Rq<@r_>prAPf26L5o;!eKNn{3f#VnRE1~VX<$07QKtbe@C=V6nfH-EOB zY<`vGDr^1#AzW*srNBsBlH;yqri*(XDXuI(Aq`@ymP9R53um#AmtXpyjm7#jHUcss zB@4fPvxX#k`)ZesiOr*H4ZWlD|8J~C&2!_6|4QBl1)Q z72UQbN{WYFCBF%)$mXt?^JO zOk()a%fKIYKz-2zT>vkk`ZwN&_(`g_d7y4{;FX`L_hCgmDpd#<4fX6(xr40u(v3uYX1VHe;UXpI^e#$%}|^@D6?wPv(L5j$Gi0Mj9D&ONhv zUSF(}QNpp=O7&DW8x>yNpF(Suq{?{&l2<{Jobw1I%hjQCS!{TXD&WB`sT~EeYoQI} z%|O$*pE-A36?NTQJoxfq74`I7q=65qP4p;$w?^Mmus){NbuEz6_+=Omdlr}J*Aeu@ zLWA#d>50(BNkTwLqcMx>(rNbMM7$d zlb$r`fY5i2wbJWY!8ra+rJqJFO0)rwM3OKZ()o{v$PoMR7Nj}10`&#bDkaDLX3i@{ zS9hT|AocG+`Z%BP39+EgF{Pl&l3d+w;#EGn?E<1$WlwDbt;PA9F_bV?*^UFA;@T|# zyBuc?Jo+e~kHw%8Yx5M{tT)KFw{iK5Ln z6bgvbWem%1-eEqG02_1$ou?H1fZ<;D-0_xp>Dc9LJ>mI0gjSmHML{4P5Q& zYFC7AK|SX_+K`qfAH;7KA!g3K4MDE{hMWgD9iVdFQT>0lYF2JIod`86PZ!u|J!G15 z_oK@x?kv20xYQ=57y93La9Zs^tEprI+&WSaIVtYhxJ|OuHl1MZ*>DYhS{5`J8qH*i zE_b(7qFF9!679}ziA1wVqv=63@Cvnz*qS;l)G!t_=_zjc$a;!q)~1Sow{818;mG@eGY$v39OL**HQ6N{Scgg0Og z^hP6f#m+<>w~wfcxFbcfs<(!Gaf8Pl`!VE09)>wzKux$>`BO94*#g|vhQo$=EZ#A` zxzxBFbrzn8#+CNs^}(`T{1}uwwpE#=s#20SSoNJbF9!tO{=`ozG%e$-P{w(*1>Ua0 z2qBU;i3DLK?n7NK@ank^G%_o8YleXGd4^HiEeSD&j zfaDKmSB5nzBaGLk#xSJG=1a>cy9i3hQjwXc=OPmz@kRlG^IUPSj_ykB)DDSoGi4s! zkd*D9n|6<3C!7(zhMRWR_-dM;VCMkJXa#E!1!4$_Ztk9^- zcD|IDauS9Nf|K?C)8psmV5RT`rX#9j?B+=a z#+WDUHaC`0%y}gEF@~Z+#G^ z&du<&NqG_AZqpPRQ2N-oC1zNP@RslDX;Jomn4=B4j` zK9A4i_s1`fN9J|!x%)Zio_p@OTMp#{tE&3}q~(Rwkcst5T8HlFoMV%Xs*5*0ANcf21R!;OK{fG))m@5ea2k$N2)3W%2t*8j9eU?JO(y$!kzBUPS|l zi$_3bgwpYVV0WPU!u>0`6VRz0-4N*91%*Zm!GwDm8p?YaE%4 zyAm+2>@QbZ?IdS#2(tVPx~JPH`YMbo7>@0+)v3(cun;*m3cRNSJvcUvKIia5#bsmF zp5!0m_Q#Na^)sG7+|!p=TdXwi+XtnNS`txa>tc+L?rw}TEGu%u21)SgC9I5z0U6nYD||76^cQ2Dzh~VC4S`EyE>v zkZLJ_A!tOduxPDEM0EiL+GF!~Aa)7$9DD574yUvS6gWzul{(#4ox4)38{SUmPS&~0>DbHbas;DwInn!7IEE_8(HBGuNpLt=TiCCWZ! zCih&byv?dK;qNR}hBw?s>})fKcoUyjLm$9*VF*cB41Pw~kyQu(YpK$c#Wv>g%an=A zQNCjtj_`QboA+L+q_J)x{Lo6J9h(rmYL)Ve&)W?U$sXzPrPNqn z@ZqbJx&g$9>dd+j7f^smu84z=rRt*)zGbb_r;VpJeC1G(D6BUkV-#uKj%EYcQ-zz* ziK#IdP;#|(Q{Hl&5>S2AK8l8c1iOmR2uP;xTy?_^Z?#gj{Ad--{vL0(S_!iVGZK1Qcp$Qn zJ5NthrvZZW8&6MQ2!(3(zFDePeP~3@hHl9{!q-FF-{X7WHjMxNlvZ=^HA-*)`x_BIx@2k{O_Yk) zVT@|?5BWQ5aBe80q1eQ#EaZi2l(wu*L;h?HPL)+|$Q!Oz;u0Til~lWnn$b|!6(a|s zehH!8zRf6f0I6h|tmCl_ZA`#_k@PyxUaRzNvjZW7dN)No6U6RiZ2j*PH8vI$^?h|W zMWemH;Ard^0$EEzr(x@G8g6KPeqx;x$Ws0JpX-!Zrqt&x)+>QY<@{w~ZaUxdqg)_q zB%K@9p^<8QNN6(IRvw@^U@EcVpVUT>zCi>?9~(lXuV4P$HBfye-@RT58ae=Ua7=ur zjcKuA&}!67@Fw-YwE#o%H6oZ1CBR*g+*2vd9FZm+MFE8wVn#x@Jz(237TC5>eYb7o z5gQcW%3d2VM1=i~GSBlq8*tV-yB-CDt;Chk+BmTsK*!dn&T)gVlJ1H(25{&0kXoCB zxUQLin#={xojXi2KNIk0T>&2@Xc1ZZu>h$AqWonR*t~UK1{7034CSHiFnMLONU)pW z4GFHP$U9{GjRda@_?L%ck(vi<3ny1rq2Sg~WnUYz; z-rYy6_R8Uy3c|%6SFPU zY)b|AV(7hsi9d0jMYHfwXM$Y^7M`c*PtwAZ&;R~N38+Q$&p0I4Obv<1;A`G=qY}`n z+J7a!?n*obE*LHnJz%+@)Mo1)K4qiQu>Am3Rn8Ld@UF>vF3HgC7rKKg5XZ}DUQtLq ztHq%1KA&n9c7Y$;sF;;Ec))+ai?3jt3SDPkReeyC`q1a1eaX?!4VfXLEKFcwP(F)5 ziJWMOm8^E8TnKbUXD>laL*`%jr6Xz6P0facOcG~5iV}TLCdB$#L-j-t)Ax_P44Ey+ zsCND?@_nL1Pz2RhZt!h^1Vqpg1Jb($vV`B@}SGXVBdqFO~Om! znNz&UG=s~|oHJ9rjt#p}Nn^65N~Cr5!9F~r**XH(s}>l6`X(O9^uBQ?B!wkwmQS*6 z6qXKRl5H(tqGx5zmgJ`AbxgyFo>M=gt>#-D58;>kzrX|VWO8CBfCgPXcCvm4z8oik z3@Fb+ZQn(9q9E&Iu?P0h?^CLunQnQ?l#_OiHPMj;2BEu{ zY!N0~Z{kro6Gcxc{1VCRnElhme==sM8a|3@1V*$F!-$uLdR3?FhfrU76=m3VZWO%n zEs05W#{$HU7GoUV#e;;Q9I>A`ax6(1nX6Il3GrdJH42G?-IBKNj>F`cFzSPQ-f3rY zxY;%a+0%1Ak2{lX^Hx$D>us2%ptrpZ<2(wviL6cuL+5e< zo`mc!tE16LXxy*>hVMd7VfGeL$gRXjiuq(5OF*@LpV}`Oj2w!7X0|>}3X-`^tu8KH zrJ4nctkUWwhm~?m6Hh-&Zi4l3R{r!a(0a-PRsB6}8`^%j6UMjbLTru__<>2-WKT1y zCACCV7PbKtiz>kGP|$2hNVve|ZEYqgQ5afM=^xd?sGJ;K>O>dSsyZp3f2wIUC|h^6 z`n#)jO;@dG6lBPpCQ88xS^E^Dnxs|ebpa$PYmY4bkVc#Ajih!!T>XKegT&NqFJA34 zrOvD4L&lIjjTm0oKTFm75D#>hNvhD#Zm1c=c}N-aIz=f}N33x6Iv^LE5&6?c0Uim4 zUAuP^-=%Gb>C@*koaH2K8240>uz?bS{b;3Xz-W1C;_Q$C3D&1-33?KkZ2*EGPf`rK z5<-TIg6mboHwhub7AA!BS9hn%La!{RY@{5P-2Z1)fZv7;r&LpCphJL(aFjSRTWM+eY8%C&{(zo) zhlGNCy|^+0hCDjZBS5xrapMAdZia}CiG@=`r;dLG$$&SLm9|jt5OlCD%@*X4dN_@a zNt6?oNJtX( zGl6;M>u2IP<_gLWSQOP3`;y<&AY!}~%Kan(LAO!6E$dFvX{8?_#|Pg7x+cCA#4X;U$!fi}ehdsTg+D5-^>k zKU`AeXiYa{WzYz;frf31^$3}8L}jf*F)pT)rsL-*4@1YOB~l&u6uG>l4zxl_>ST7x zz5zTglL!v(Nik1GwNC4)l)p4y1#&d04H=In!EUlBWQn|xsdoDfLfcG^Chm{}xLRzb zE?wwY`BYZ`DvCh_oaP#fG{y!`fkVyNga(W@d{MR%Y}qLpdAVR@1p6WwLSUO9gaciR z^aVNTNwD5jM?+WV$Nt(*HS6(xiQRiMa_*#k_Wjs?^ar?Cf30F6d! zv*Y>$#I{EcTth<|u1`R*B-?0_m1I!uf01sfAUsJo2pybOyrFI!Nfm;5c(CZDYVl&K zfR4dBuGLAm-=OUZ=@ufTTRG7oHR(o&*QwQzNhI9{ROj=*Q0iM6X*nm0oLzhbTfks% zDht9;y<1IlxkXrAk@XOCd?^kts~0NBs-fyqf(071RN@rD91v3;BA5b~dI^D!u}{k^ zz))3ng47Kz-S=n{MD;s@&7&vkL?>fjw+@FGWj9Xz6b zSzlMJuVQlMY{6n(!8Kip3mg-4?%O)INtbCteg1Ba62oo=@vn1~32deh580tKQ1W^A z9ZDNz5}&n0iLs=DgH1&lWALHBgJK^DL2@+6DCCDA&50&5`F9$WWOoOFu8(@ibN6-w zcREpJAN4z8W4Zl^PWcT$aoPOnS4v2~jfe-~cTj9ig6orzbgBdT`+x>;sNJb05P}2t zOd3xyNx>LpnCMlyiu!-1jE!U3OAy&m9sBnudi}nNC+<{2JnMRt@$oxxnahvm_>!H9 zFI&2bXYW*^{mOe#p29pwZ!OmGq{?}n4dzdFD#oBc8N84Ve~A9MPn00f*8ReGJ58LQr44DVb98;0hcBS zStf$EkkC6K9YIszQg;z4>{*jsaR*S`__7y(Zb-q%4OQJ_-7torJ^6RJN^MIdhBPF> zppQ@FL_5)p@=K@uqBasVH(cZg)haiKQZkXmE*_w^M|KoRell6@ag@XhNz8WflraRC zdYVQK`^tP8dhL-uBJLTqdm&}?>qn4-X8X!wNJg{ujM=*K4uLlzjoH3oqfB#g5iRy! zHd{9=p}K;;c5~-+7*_5h+OqJqF zHGoo`pzdwYHM&xHYpKGlE2mSk6Ca8Q9*B@+rEKGuQnLvs=@h=>Lq2mCb}kT(O}1Qu z#lKdTOK2?1C9IX@5_$kZgtA;}cUdmAvn*FM<`29kg_jE{f1);hG7hAI&MIQceQ-62 zO|-Yt?OAl_48d1i!GFC#aIAbM+GO`y6-1g#Rw~s8+=u3>Cy6h#7wzp?DKdkzt_;3@ z!6)uh{Mgz`eBN%QW|d-B$gCH9<8H;T{_8S>bXmzIGJ`{|XkA|LW5{4osEoEzM$3`W z@?Fs?QbldDX0|-S4Juen6)Yv%+4Ayb!eW_lw<}@sbFSp$YV^Go`RjX7!Bkhsy5~H7 z52`+|B44{l31)9R=X>@jftEy>A(f%-A@pG;{Cas&NDjfgAh)O&RFyF5Qy^`3D@OJJ z=!&R|;NCxl1kDq)wMT|h@UwLySa9l3GMH$M)Dp6w@rS%(^1@fdoi6#q^air^|>b6tSVKTDks1hu%lZMlz-E zq5y0*kR1cD^JQ}J5y`zN`Aq6pw$0OJ^3_OAlZM|pWx63_M(lbo$}$2AP#ZzW zd8-j%sJ?~5ldKm^(f6muo2Wga3vLRY^OAfe zaKJ%9pAFNI$d-sHTy7MQXcdYxG;UIK)#XoKxb}e!SpXKY$9mMqN{>wtOHQm|)1_M4 zWB?8@!D1&%ejs z9;$?TkMg%?971Eop;RG4Dd1O8aPB0yQAZWw>Op{t@J0q#DxU90o~DNC$6!r1e@_8mlZ?b8OSq!_h}gZanLq5j!Lshebqk8I4Z%K zL9-(0raR*ZOEI!iQ6kq_acVQ^_Y;1x#a{J$%s>4>X(BIi&7;mktI|9A@ryqwLn@ra zqK~@xK94KFfIIy@?_Z!aGR+{M8ILAl)dF_wJLc&7X;;ANa-6~uWfGFj5sp6bGGEmZ zz$_wc#%>cYC{SK$=x7hz>}@0eX+1otXWY!@&N9{i+aK*-%x^vo1*O| zWMIfFqLfzqYHE$ud4UnoL4cyJSUbUNtE(S+3(t+m`D$SZGc-}z0b?3jDOw=J|RW$kN9nKCaEq#Qk zB5wd{L8$CBoW~thCN~b0sf~oK-+(QurP&5+H#X#cL`z)Q-T0`KpE-!8o-XB&4=P;( zmz7e9g-8RtAXa~9wE(LfrRt1Q-mgfhU#CAJ{1=wvOS!#BX+J>lVi=a2&SF{16FVq> z5IgK@v>}A|lYd@faqANL0U`VkqK`F8vXvl{$u?;WUN1>S9~Rl!5Gcrig(N)SNn|)j z`B?=`1hG;MDZxqNy7+VGw~;)cZBKlx7&l>k=p9?$ww8Pz6=(r085N5IO9^~Q{R ze6s}DCcvg>F_SZ7bs_<113T3{toSNpdE{YbWQEFDAyZr4;u{Zx!~JgYKOJ}??bu!+T*8MQ!7Z`9N_aZH z#{VXdb{ZK2u;GI(&G`36l+bP`!@(N%Ei@}nvK}Ye*9YQ~_HElL|B`Io#zdS?itd(b z$ZUtc@3Juqoz;4dHp@*c<$I6fR_R=R^{5hL$rYVa-hx8L$+Zg!FG6>rZSS+(JS7(k zn%)#lCV1Vwu`^RFD@n~*ok+Z#J6+IHc1W2YYL{xVl{7f(bta0Vb|*DM?qKaC!kykb;hx2vS^`*V?Bh|Z0LrPQDQ+!>rN@t>ziVhq@#|8%=Rro)csCMMx1wS zA#gnpp7RrKwA+Ce0~MrU5LsGNf015Y@#RGEd1Blk)O4I6cwAB<1#1uKRFsAWQyA`( z73ew$bh&DsE~_grWte{$0|&(6VC>&1#SW#i9=3A7VXQHEUWy)q7zEJM!yP%C{rWG!xmihoQ(Z(SX>u9+mLkx z6?9yG%6*QbM|nJiClx=mWk6h$P$~fR>j=pBdIuG7++{KTCqsCbE zSJdCf5#_W#)NPFEpS;}`Lycn?R?3|{oObO~IpgkG5HkOsGeZ=FlUyjMCP0ob7u-}N zq%08U;h6G>^2sDOE=@w`aJ(Z&GIba{F3ymQYy%%@!>q=+S(&09GCeMQYWlNM&o}_1 z0Ws=`KLq;!Auiqs<70nTI<|F$f*tpY@c>m2qt8K5okpJng5m9wclXdfaFc$lzHG9Y(%}ZAK0Jw%md7CSX={jOro_)>Iyiug4J%i06QuA($oO4zKLX1W7@5u z{`IB^NyG6Zt&3{~=jaQL#wgzxr6$?CVU_QoA+sBKY`rj=Z^zhW0p{)};bnX4(UL$X zf$d$5C?PH>`l2DTlBjV3?cTDD2!$y?aCh`?X}^l)@-9LcPch;`Vnk8nK>{p-=b5cn zkv~O+E^f9_N$4<#P0=DbE&*#S@U{90IEacOA(|OZt+yU52?iq>(RP}%^`?%B))ETB zl4xtWDWA9bD8wd8J)}iUJELL5Y?G+4Eg^~|VVMot3TflycdKQ7 zj-V1|p2g;{hvu+5rte>PL0CaQIcQjLzmbQ>l&YqfmDChN)>c%TI(l>2qfHv)J=eIP z5E=$XBROjna|hC`ESHEaH_(I;vgyVYIqiIs4zDfG@>t}7$MY_!6=>+N<-I&z`r)bo z8o{`D-(vRPG~>t$C!ckL7|pZ>iKD735m~DMl{{Z`soZc;1eCms6uMcf$hG%qPSEUz zI$734s|c>WRLkT5@Nz{uT;+?;DgohjWre7bcvMq0xVxu9)28T?hKwEMd81#IsOs%ONzjI*JK;I|CZF)D zQm2_gf(H-^<y3BKaReT5Hjv+zT4N;WDdQu~MNqu)O$`Fiz z3QLB7K+B{VlhbdDqQUN0vBBV^y7Z5c`bQ4uaBT>+E!ABhK5H(+W(v2P|94r2c7{r{vm>ABS`{n{}k~T zyW{(-Km2QgATQqfywWa+gv%bc$c7Ssp@EQ$>Y(3v=6R)sXHxWI{`Gk!!jITj;|**Z za?0oUtE43-w|N62w7Z?odDHj{R9hiDA+G&EeRIr4BR+=A|9J8_7nE=#X;6^R;tzwy z9m9h4^$C|^kXNf;<;N~4YgyJsKK7#0JLDdkCW;X_a~AXWIf0ZEpiB)v&o5n6%zp1V zV+tZVV=g+!yIfLIi~%B4N9svL181zDbNs7I*x26r2|sg5iR@Y|n=bPI>sORzkDND7 zPWT^)jw5s*Kvw~(){wOk3Y0x^DS>{v&R@9bM44!kG14gADr1m8L85#>UKnww1b4O@K{+TX6 zw(%g(uFynee5zikR=un@z$!^t`}9FI#gOBjg!NND`oSQ%l8{Hi80x@AbR4)e5dFzc z$hIWmy#;LM5VnhWD>fuy_Cokgf*aN-J0Y3e7{$7f;38~O#-YHxlPdosNnrF|0yIq> zuFg3l*q%~AL7v(Rgb)p}KrbMAl&QC{OqpbJl4F#(5GYXXhIG`{PWWQ*pX!V2iA#>k zy+6Q!gr?m@1GFLL*k~}9aTS6^lYW~@VH_HmU- zMHV0u6=^}4Pu_8rdA$3-l=1+q3RS zpHLa>UMmnYiRJ`*u&vrqFOvGdG0E0H6tYDmu;qzd6sV^ncXi!lDq`~(uszA`eHbwK z)T>Iq96-|%r@jZ15e;|$rEgqEDra$0bYKrK*^aCHETXSQ z_0=oC@RnEcPVrKSQ6JHy7wT_vc>IS3v#%}Y{UsQHkTZ!IvTqrrh9qQ^Xx9W7 zg3w@GDzWc2*zFaOS=MfT>Z%gr-B9}Sx$+x)k3`k84)GS`J0g9>d?5KglD@M%i+oe0 z?+V`mpQXF>sdCWwKusY1y&({3L^&vy?xA64c>tmY%D95uwmfecR|OBqxWo+<_X@sh zDMm0bQ8C;H#V>^jtqQAb03s|08CcwQ50ra|a=@SZ6{Xf>uyZwXLk=Y?%F5OvVQAV2 z=fNz3^M9-(_AIj)gD0+vOJmLn#x4sl#@Da8_Q2dE9K5-D*M2v>$gO16i!Z;adlz~@d zV6$U#sj#{XjFW+9W#HdO8uR@(lnPCV6-ZwLLXxeIfl8qc+j7SUxUhSw%g?;vI|>!ws!7maO6q6|DgVHM z*T!!D%y&4HTD62Aacb^24};}x+xb9M39g4d-(m)@Ry``XmSPguz8Fee`zK$iDzPp0 zB85|w39c9@04pbmhoUl?DSbzwkge*#gOs7PL(#h^m(}isRtz%}(eE@%dWaVJmIbD6G;BJ`#T-wi ze8*ylMzjQ5Xc4?L;y}0*sC`JAiV=g4A@d%F3!A67W%xdvur7HfSepUk3n?S3*o8+^ zH+8)b45U5)5s~kWmE(Q+(L^4aBz8n>Oh+%NUrTM_WqtOiB5I3st=?>p?2o5O&|u;P z^{bP7Q3+O@{`BP8B}!1EVqwk~tS9eZMXsNqcp7kQn`z3ao;t}LB}%ALnb)|bw5Xme za8HZ4g0p%J;wiV3PBrIhLmotslwunW^8egY0xh&%ln^;xN;}F@XGM4ip&BZ&hzgHl zSiB!3cU}Q9cmV2dkKJ|`BVRkoA7g-)h@YwXZ-U=|zDdXuJwWh{tvvMnvXlW}b|jm6 zH=q?>tOwnkm!s67{Ny$Is$?SKdRNnHo#1cXR*WrvJAfoGaFFHy%xkVB>tqt5mn%t8 zG2eAt39d37VRWU+4Yh6|zj7OE?0s+{i*_qM8F#QYFCPs!Pkj?>@m=vH%slHM2um2% zVdhO3I6&@y;H$HQQj-zakogL_fZXbx2$!0JEFCd$!6f#IWEQX!F@)2kch-<~>n^N8 zyI@M!Y_npm*aUSAgjj;6IU0*FDxFx6j{Lq*iwb%EF(tr4Mq6kpwLl9nh>%1!G5$C% zAloHsAl0C{%TA9;?Qlpp%pWpEzrbEc_3;rzQH9YR*By{&K58td80vZQcW|XwkB~pp z6+V=vabpV5!)=KmPSse`OP77XNVpK(Lp&g^yq^V+%oxKm^;eTkZ;LlspP9o7aFo;Z z{Zr43JtjW%juKsI5TODhpw}V3@s83~*n`g8QIabi!bW@|SZZzF@~+aW(hOR!Lc}pe z95*mWh=_adD!mQg#}P+1Y6`A3*@J8HfP3f&pJ6{3*h8G#QrCVj=DTSyX$!NDHjRhS zI(r9+io8zYLw_c#*J*-Sz0SyhUz`E3R>#XpzR6m9E1=e@>nVzy- z)#PJQ zERLh{{QI~iQXU4(^8o=>M!iSwu~a_=Bfw4Lry2l^!aac8Btqaek-G-L?Or>@g8+F8 z!FDG5q+-fkr5~6n#upmGvV0JrPJ=BTZ5%`Hx1`$yw?!Q$J)soPhupTrL%J($E|#Zs zZ=N0Oe1U3cfocOT9lOv^HO8Jr{-q?UNJM-`9E@XN_S*NmzQnIx!*RHYH$PjoZve(-&$gf%=RcvxFY zE+~m}Ndh?q`xL=E1re2{eC9(O3Cs2rTO$-Ne*7Ui&A=aooDs6o7URI`Wtn^9l~^qr z2vErhY44_uGqBE4rKuACx1AKDAS1LCVxZTwGBLd4$olj+b!8>q`;ihGczPeGrtM(C zvCx*T9V~hK_?Ac54Y76~Kl%vssnI7$xW>5`SZ7fsS1iHAg|I{Y+HsP2J?tP#7IMkH zn^xG=txXZ6oFfJhOI^-&E}K{_!h(`x>#tN@{az$PR<#?D+9UBJ11zLtlO#7}jr|=V z1^9s=jyr=0MPfsYsDbY>;V0Y*zx5Z&KF6w-SJdA1>q zI+0w>g$xku9ZA+-pz}cW>h2~H*6>XBuEM@jUmgA}_(UwcT}b;wYq;4eRu~-yY8Jw< z*qe5^1P_zqelA|)36MDv)pDfa$2mfPC6HJQJ=&-yw=Rm6`B2daF>E^G$Xz6OK{T+- zA>ogMSP=eCgy0h4j#5H~^#?~oG#I(B2KKcG!0={2#e|zj_1o(}R1G@G=fVvsHpyog`Q!UT(@cWQ{?$XZ?phmqxuHWeA z`8W7E3zs~wRpb~Co!WVLYyQ8u$?j`!^a2l7IHEC+lSgt0R6?LfFey7z`(tW(-(aZ= zUAn;0Pk5yJn3j&<19k9ZoqM>>Jyhr3pi4Vl2me6_|3&9sPc{o@jdGySliRUb2OOny zSJb)p>)gNV+yy#!6}KCMU{~?xhM4|4UWesK6l=lN19q>le+xqMUqA1zU7XHcpmUdV z7vgwL2XCiy57N2U>)c1qTigZg)CC;SxsU7IKk3}XI`=r8TVIJiI{1E_d-DZ%`yD%- z9<+Fu&RwW;AJ@4r=-d@9x*OoHbGLH2iyR$Y?gGa_om++5;w1hLx`5wx?t41-Q_U@z zydIu=aFAV^vXG!E1RC}d=*bCy&b$QrgFve!$fBh@Nw8;_#%Y;3K6SYdI_7I`>JjX+ zyTP8C8~0W^%IV<#E_ab5z~wG*RKyyGv%PgC+#B*WkohE~fCVSU#dFpVafW#m!6w}L7y$3t`05WO` zPq`cDYe}+}#rKczmuM}Fe-&HU`kAb!`kFFsVV@c>q)AKYz# z^T7$YDZyGGZGiD**fd6~@6k7>4z{()c+p^Lk3G<7i^Uzw~5-SevhT<#H@+xcAqX&EVK|s9HByy1dnLyV07A1K7xS zgEk3z;7Mgi&NjfX?*|*6o|ni~eVi5C1Koc%njw{PIvMSaV)loV9th8@ZG3q-)}D3w zf*&o%f>_8G{AM{elI`ElQ@r5cxSdb%Vu37UJGXhU3GDvY{788g?1?t;XXRL6Q|H^_ zeNDFE-ey}9%nPOt6tlZz+=75t-kOKtY3#JhB~5u;W#->!3R;7!H}FcupJ~@9lr9~K zKvig~s+xv;X=ag=ET3{Q1}IVJ+SHf=_CX z`{2LZ$t~qs4>n~de}-0+O9N_nOnap@-%yeH@yH6yQhoOqs0c`dospMem0q)z7gk^m zs|_h4jXAOrJ}NGTd{}{vsIh4aqJje0A90WNm|XjukMm}cmi0S;+%Z6|Rw;VR4(yA| zCCC={NWHZc>BQy_XzjS60%rtp1AsVZ_NUqz<Uiu$i!cxo)Lx(Q@QN%f$djrI+CJ01n_5a^MhX17 zTaKVn@fimd2hM(>gJTlhSy}|8HB#M%a0je<&bj3}@(Uw_W>6?q7ZPX=qQIo8&LU4L zA!WxV_bkZ}L9~sn2GvWQfi~}jg@}l~+0tGFJjBqhzK#IEZiWjGsR-&~Qg834fV7OY<*>AFbvo?UlO9=aPcT7D>T(|B@7JvrSSk z3i$Xh3f@P_l7c^Okrd1m5H|%|Y}F_zuKJb~4EPpJi2OoQFc3}o-zZ4TsHY$?<3A{P zmOxGl9wCpQpn|nOC-#T85L6j<93}tw3E&z9A6VLmfNm790|B652N|~wfi598XC93u zJdoh?DG!Z;=VTV11fM`~je>tS7g?7a1H3=rP70nQKyAVk=E~LQAVfV2e@x0OLphLdTk@gruWmv!vri)JWW@r1iw)PbD4agLclI*kKnM(r+uTSclE9 zpo9N!WDG>Oo{W{r|8hrs3~qFhv4lK=jP=*MNni;RD4h!>QFRb`H8R!?#}jGjp`$3^ z1Oho z1Tt>$L5TVoxK%yD&}y%b1sPkOFO_6#_@N}@vj);%Q}}VWl;-z@-%yX2Rb_80|B)TA z&TYP{2FSLFm(&2+*8L0FmZMNfwy_`cL<4J9T>#v@@7TwZYR7RGwUcUlccR{>KIPV$ zpc=UAf1}zugzKqhBmc`(n@%8S=Nm^JLAC#^c4NG(k-+SWgD80H2Ea9{t!yr-_6G&@ zMgXXGPR2b+pt;D+NwtF#{w={9Qyv=CX39>siQv@;u2F5hjBg|OLvWCjYBLFt3px?i zf_;!eosM8N1N^8S|4>k^>EK(EN}JY7s?Dk={mX^FOdY5BGuHC+ek_8etl`!CSvae^ zhR6A{&1}JjT{ryMDaB{wDk9LFJErL8P!*P~+I2LL{i?8CD|USr%xWv_&I*plg#%gF z)%<*2W@I~7@aN<&x0(mkV-47(6}(eD_zO56T#wZs7FQRwAIB+Ey0q^#_*4szGx{9HX2mOOA7 zrN_d5G!z%qI*I&PgQ)%iz8M`uJf>Eo%gNOUz*RGFMwMY?QgaJjYKm%G!*?3lP4?4D{t=Aptl<(K(}0Cn_^<)$vu_E1rvY2Z z-dw>eHe`L7&x&2c8nQnW=4a>K8nF#k>INWIf*rM(xRjSRVhuV4TB)4dX?WkIR9$=x z$QVcjfG1)R6eL&uuC0{NKqPjXvU%tFL3Jz-wZs}EI?;1+R{i}Kn(_i#9NDi$p*<*H8G+r zDeP?0JXkI0y286C1RgXeeRhjPYf=37rS%*aM9CP7y5rDMcfY9yjd4&pM>nKPhL-Ow z>)^nAsto5Sr->v|VZG0LH)hjWn??LcV}^^y7xDXzSxa`_#v3-lcbkp(ZNet94mN(E z32VhF+W3PetR7R}=f0sVlfCgiUmwa|Vb$N~w?i@Onzxt_4P!a1bRjo1WpQl#Lf*S6 zOJlxveyAx6VLl7_pH0~uwsZl1yBQnHx-H;mo3Rj2j|DGy=c++H+u@WKO_KlqZW5Z= zudm5^1T$qnb=E@aKzNkJ(_|kC1{ex-K{rpqRQQA;a}MwA8|3e6viCEZisA&pF&Q&i zlS2>2`S4#mvPKbSvCxWzq$I1n^>qz$PqKq&<*QccPffKOFNe>UoWToygX#@AVX_Sc zt>3|s!Tal#x2&xwW zJtQ!#geqc+eg?65dmf>vRJ~4Lnsi$4=-3(Qz?*S&1#`FqG0H^49hWS6UVz;){x!{7 zVYW~7CQAGTB4pf(!lc>fB~wKxUI8Xqbpx$3+onNQRWn;}msCMPCfi`VM0S4aNV84! zxa8=2kWD`m;u^rDVifWThvdxGDj^nibSBBADj{Y%HwVVAXSNm#qXr#wi#{}`rdT7k z0A<*6cxdh>h?0*?R_p^CjK|N;r>&&V)$=q#Srky+W?C#zyvQ^qoQ^H}y;@Yr-B z7+s(y=G>58i8SS=%`p2j_{Lb)xbLV!J#!?%j-xS09a(egM~*A-$bq&< z-9A(1b7~Go!8;3_rlCSL6K*PC9}04haA5Md=Ik$J)J*|WII{sDg4WJYy}(p?yki4tbxK3r}42- ztQng=k*|tkcLGLDLWR-qa1nFaRC7{Bsba#b8D46yNql28>&D7Y;%YQ&U||!8kfQx| zuMO`9c))!39Iu9%Y!=+q4C;w9jr%5w<_~r3oF%45TKu>Fr}&Fxd^Ho%fi_{~8tRxf z9%V^80o{A?C3uvN?aW#Zh@|M)JOzLWyO8N4iVYU_5PJJnNx& zo|^oEukE8u@vQgu3+~fb3G|#i=>>1uSE;9r-PNfpdtYHAr}4uH>>%qnmM=?W=?xA~ zrSdz5KxGhn@NC{is6WK7^&o_2ka~C|Z`%z+NYWUd)r~D>-;Cyd-P!7T!l-s_G>b0KSMPoTnVy%)CsI{^u7C25r>vnfEg2unPx3(-eg@H{mc0NP(x-3DZkBvrV zHm`PYLteF7!VNuGSbGYI1Iqz-YW6tX>hrVEF295JiNkOJSi82x`O$@6p(uJ@Ox${T zxdNZq1NPSMM{|1*ycIPY_@hXnh(yxTb<+$OYzd(f+v=R}PN%B;QV$l);@{xUd$7^% zOmDv^%b4ZO=8oALBx_z-5i_^%7NcrCKn-!2Itk=NOSTd)aujwmFI4>aS3Q|urLTy1 zsC~d&{Fk1XzC3)JKkms|hje))NK=_ota|h1Y#!PHocE@d%_uXnc|o{FHlxP!g=S_9 z`n*gew^K|%BnRr|!41^SwDSXI)~pkSShZAl!GqKa!{SDelzZ#Tmb8&%4xyM|jsz}g z`=~GZCXePVl37H9x?1}ANbmR#yFZqYDOOFT>Xt`Y`>*r#WY)Y!j)1tan0}q_PiBp) zOn1fXb)DZq%<6Fx;zW1#>%2uTR)`D_hT-Qb{anD0WTisKZ;SYZUaVJg z4w_02D3+?9f?woQp5SykT!gFJhrTGw#9`w5Xx?6IR|YmB&w%yODid9QcanJ5=G75y z)IHM1E55>7RG^S9qj8bdE1q5{TS3shO=QwfWzriEkm@@k=@jU5v1iENU^wDcmhn12 zM-g&+ZBG%cFXk`wSf<+X4ZiFZ77@A!xf1c}<6F{3GjPjk5~^(*B11=v;w7)J2Caq* zKX%nVQri+`5haK~wtey?F?(i+3G)ysI+qRO9aESen?8*9Phqpzv!VQC3hU0k8p?xu zvrx8hDDT#rb*YsA+?b*-zKcr^!EyoZ&0M1JA_`Vd@zLn+M6Y^FNSbqA2und z+EanR%?r@#aI_i-Tmv@{xNHIcyblXYq>xS2jnKl%_{L|zqzP8bgLb*sC~>q2G6J~k zNO6lmSMfLsJ&hY1Mxd{U@$s)=;h{}m=GQnv%WDmg>F9$@B@LcP@M6H@ZS4`Q9eJ06C!IEu?v`V_zS?RMhUn;Le)z=q8}{VYhFWd z`JH|))6Y5jIfWmm9KM_7bQe1AWbt|Z*lR(xrT7_|NoX2ORq*N!HxSt)lmFF^)lZ_3 z5ojin^#};>mj6evdDZA2Z+R;;H#)nApi#@{M|>KOfeg^)ODoE$Cv; zK(>A;(6;mM-UEqJvj}o}C@)?O2DsXv1yq_xY=%-D!?@RLtWlQ+GHGRsxC#V!C4GXc z7t~jY$k@?Or092zs8>jd-$q1KBLPcH;B;_Ti^yxlcnIoAUo7|~Sg%OsS?-{u9=ox> zWHBe!C!OcVUt^71j1h1*HKNWV3$3-8kUetW>bt;@8r+Z9AHYTj&646{`#jWF6zNJzOZ>H^Tvu)iN>1`mZ&jrkHDDOSUYw79VB zcPEE`gLKIIP&z8y7lHBiM2y=lw%+IS2eOdbzk%2AI#AkmG;u!Spox}r{@p-UzZa!g z4dFF-C>kj@3OgQy`c7S*dcXkGU*FEqU)}Be*2PIXRG+@Qt}S&Xq7 z^#Raf8u3>$3bc=Qm~Gtom8Memq{qC0|2TG9W3pNe+$ zb{D;xBp(%BE<~*^DB3ZE3NGx;e;mR(beKV`fr76R(p{yh@1T;Smh25r!?}BmcbC-@ zub^Uc+6oAr1Gzhh#|{M(c}vN9W;Uww1~BPtas>(hj^I52r%Ur=caZPz6vWbG*LS6& zcJu;oBSb=Pp@o!lx)>+jF+4?#hZJKsV$gXb8}}Q=YVgvbP*KvT1<2^)YrOg}77^1y z^M4HX$e81eLoUOhLF~n5Un0rWKLiR-%|eY*K`IoD3LYeH^%Tm$pRXE*T#q9)<=XBw zzIzy^g{xlWkB70)_(j)6`r4FWV;^Vw^5pFeR5=@1>rXfOXCRuU=Bq7U;ja&8ZK70S z24tUtuj38$KNts`I_f+rcd}+8Pal!iYX;n4?{{YMqr+JX3x!y;9BzQP4tje4WYY}p z&u)o222-?b@B}?Vl#oPMgM$xoG^P&la2av5&Zj0IPEtmZVuqR7C+!lt({D3GdFSba zcWuqKee4eKhY6t}a~b2)Q<-lygsC@)v(St_{rLJ+)`b1ohZo{oby6}lnMRAMi9hov zscdi+Z-C^Zv6oKp)YqZC6`KiCF2pJHHlE-gz7FkewSd#$I^hH_M$9UyE=ao*-1`mI zylN;QvVhvpi+TJTtW7nwCxOsHB-|%pHTlXnSiLIQ2#_VuE#~=euukp%Ou|qV-2*>u z>8BO_G^L+L^kbx-K>G2;k5d)wHJ!H|!Cq&)ALk=jRP~GCN}RRE?ud4z1Rj5tUm3xC z*{41D;}PuL7O@DX-X15nCiFs1kSS!rIN42x7@hC;w(h~#k7T`BtDd}cBnz~>*Ne

EJ4hzjBa?0jx-L5_rd3CfkA#mtC*U(Bd?)2^kG=2 zN8i$&HyX{tEORL$S?jcUxR*L!LJ%F->(gB#&u}6}?JqJcOihZum6nG`2q#fabh9Oi z^JtM|TMA%i`?feOXdG-^u=ka!O&0-2HfayQt5K9IOd91VQM_$VoZBdHPmsr5nPBw_ zL6F5+d}#*}^1EJ=?N&+hyYXscU=L|-6Ge!;+(pd)M}Ge5R4u>pT7I=CzrA>22W1S9 zu(Vsi*PXs-o;}0Eg|8Tq)whQv{49M$D;f&8<=bo-u-g?-SteL0;j3Nn`-z0`Z^uaZ zbQk=*gqtLMfD2wA;h_>9<$`aM@GE_&qOlow=qqZpTn6NefQ(`ne3pc7l<*uEd_*E2 zHx{fGV&(6TWdVIcMLfOr##cgggeoT?Mkm+QQST*4Lfyod2vvg+E6{p2fj=C}A_6uq z@P|qEZ691t(J_R~%7PExQ0)mk{w?O;@*T?IC3Z-a5LYQ})LvRC-4gi1w_q~yOW@zU z#TvBBobOK@CSp3tAE;jHD(iF_U#gQY)#)g8I3jm`S6*!#3k=vqv25S&7OH8+A^HeB z+Pd!~QQJbD5fQoG${e{4X)dL@KADg=jGt_S~qBCE;s zCg9~>!xi8Q`ssNHOxiFMmuOY@`XDY;He2NOw`i28y1ba*nZW#fKS3lR^2~SxHAS9G z&FL(1YwlGJb7RaN5kGSIC7J1H5kJy|ToQ3hsukyEkXz$oK6D}rs2=IcO&A}$$&C2A ziL6RMn3ltH6P1WnEnAwX=4}&|RVQk$8vQT{E#%BH+q6IbZBEnfZ07LHviYZzlM` z(MSy8m|N|wB^y~w=Cyqcl0_jeQp4fK*tB*G|70?2W}%QRf|s!M1Yc<=Sq3|~GmmZO zMST(|=1-lWTvU;HXG?f*Ej!Fawzfaw%y?KkuJukWxHHTwfZIQ4eMZIsXb zr?6m4`3?xM$F}+vL-0>sL|^5l-7z@rFsj!_9P{WvF*BVF!7 zN1V<*5$;iLOP?@B$Mf7NY&1*hva9Y?Hecx#N(I99KzB-scmk|e2u zqXKi^*ozydfxO7SkBgEnjzDf>P?DtFaq@**}aL?P>9Wi34M1;(IB_a@s)1KAd@qau%X6!ZHiDwTFe;!R=7 zNL~`GZi$i|rqc{Gsc;*LCZ2CExXO=hqw6&Z998F+1j8#NL9BZ|~y0XTg+nr8R-bs`$+=zHk<_&1@HB?k=7`i+xh{aRikuk{$boPoB-1 zRn2#UR(`{`%w}(e=YfwCfqu2P6@CK4@#9NB)#;}Set?_@`w+=Uk)E~UUFWc-ol0R9 za58#@;coX99o(jKZ`Qeg8pgNHVVzl*HvHBc=FghM@(Od=5!NGu|1uYXZFO7za4u_8 zyYC#33QPf243E2QrX{Q;t#~I3YZV!pFQ{nRFLcUz%|$J@?nNz60avuhH3*_j9nivA zvqHyTL-<$ouroIh4Mzi{XdCLQBZkyv60^M&eO-_Gh!sIl8 zxCqRBI-L7uF=MN?kyNbL^X>s25kJ!eJTqhrMotVKgW>|P$WWR;3NLMm*T&lY^v0$7AAHQ@&qu;#61qgSE0#6;N+*|-$gEJ>B9`bPr5 zXl=N-Bg5;b1YU0;Yu6W0Q&DEfS<)QvhZDkhmHLsIFVN~`MX=203Q->uRg-;RIqCMA zN@;_pIzIT!Oy&eb&O*qY>hWT{Kvm&J4+>YFQJplSnL2uMg$--e+CByP`C^*ZUoL zM;i;UkPnTc)*8a_HYwE>64?h5d2mBnBt7fwVw7E z(Ymz1kt*qY;*qYWsbJ(qi&;xc8M-g}bX-rZoFZzDvu>KAb_cQuae|z2Hi;%{Z^YVT z%Msj`V#0d{an7WoO0y`QwNSgcM79?r{5O=He0Nr50~+wC6;Qj|HlX%lW$pu3BW!xG z&JL+n24kAYbaq`DjD+2!_a=V(1J=ja4iL4D>@UPLW6-`Cb$P!fti>xmC=7?>wdY?y zm)eSRM%1yHu=-(!#+{W)u+#x&;3mtspowP2pVl+}9kaS)2iD2&5WQrb@@oAzR_v!UlG z6e!9eu85J(p8`t-8hD8YUWgI^{#*kSgHr5t30@h*qnEK&EIF8;SO)&)M*e6SYsX51 zc&p_sq-iv`%xwEac6fCBa3ptp0=paOBew#abgTXSM|{q5*1;0{mEfzn-3a067hZxI zTE8fdGQlhzG1!3j207zgC2S*aP3i1H@PFgIJrwW1dG9akW=`H)6)bqq^PS)qeBK!_ zUm7^k_d0s_KRZ`^eZGAK_N?Cx=EqjBI_zxlu0K{_D@xUizEmC2`@dSp7jf1ysKXbc z#CM>!8PnXe_mxRi(#i~ORlQt&nK>h zL^wZ)FJH^vFgBswtch_{Yxii9BF-0GQfK(_+UpSedMzHk4inb)e*Cp{tUmjs7N1G} zhjsXB_$@U@q1~ETlrmANNmX*mL|k5k-S27%H6)St!8?VkJ+}RagflScusTTMgcG1e zb!{Y28^T4otp?jVLZF%f`DGiR8a1UfHXgMe3J3Yii9BMDk^3=mk3IH#a^I5fTykIW z<#X3FqlMgi0asW0;AaVbT&3G%CnHqUYPCqIiC3!CXo_7!#E$Jrc}$}`dIR9pqOW7} znxFb0Z>)hOxQGvtT^4BO}^nn z*3Hwu<_lh}PLMw@`;axPwABE#gR4I_>}viI3sqQlb>4p?8_1HYbG({v#5o3jawD6{ zva0f=|FBc+l7SmPhFZ7Mz{h@!@F@mv`SWlOJHdgxOFSi_pQLU zZAJJGp1jI77HD`-jyU$!kSMyUFZ46sZW~+7qRR7w+gKLc;l-0b$IK>@@im{Lv5U*` zN!!^1=2ebA*^bPvdGf$7s4x#c`wR9N`<3xVU$QRP8PCUliSQ|m+rDJOJ%4-goZtQu z_PXyB-Z=+b=H6BKf*jV1HBtB(`kwJ1xF7Gl1Cvy{2cNtHRqpP=ckMuKo*w+!4%Wf5 zsO&k9`igb8%qe@0p$En}+KY+(>9|&m?w1d{Ydz%n4KCIE^ts@2%!V8tw3!;Y6Lszs zoqMp(Jxb@EtaHzHxq}Wk7PveI9Lsd>4J~-UPL}3-@$qvZ@DrclOB+UE9lYC!Z{CSb zo%7c66Fb=!&puC|^EqF$>A~+lqR6;3P!6I(U}uKV_3f&e@fx|TqvwR@&w1}$R;%fa zC6EL5*y0dK`oVuw<|{%D(ZCJUOg??>v0qbI=fC;gBu{^yor_u3UJqjGBDH}BKbp&~ z`h53*5>CYk1K8k%|8F{ z|Gr-5&YWkSdFGjCo_S`U^PMhgUW@(w8C}~YS>-R0rN4JU3nTud6}zSCwsY?bsipA| zm8wse(to5jnZy1@R-Ahnewxn~_bAjx{axg6l^BPxpm`+0y_}z1(ASrtZ#U3ASRg<* zwSkB6*Sp|PEW=-9;D;Lc!3O%o$25G8)XeiX3kouN{V!U-M@o=PkLkr8X@KcH)-ob>iHuk|6(4}jvuk0=KqlHpOLCja4y=+ z-4Cd1t~71nS1j3-g&{e}lpC{~j7E*mW=E=bILN*|BpnPfBtgAmK(Yix?<=Z@3}BuC z%m4v(%LDS=FZGkw7BjOoY0-Whxs5KSo%^Mxkp3aTXJ^P#lbvpyl3cD&})@>c;s*LMz zQ}aVoWP?E*CPoJnLOiD5;BK?%^E$iD?Km7acY4seLzp?NC`j>Mtat9{M7dy`LykWk z^vfYkF zEVRD}d(YJ=A}jr3utLB+#&ZlC3YfFUcm)eWhSqn}QO5u^fwi|aqw&lKI_f*i&}s^_ z)jXKM1zyQ;7`Z$n>&x%$Tdgj`ekg>xTFerp{g7c`Ujx*+8WOpvl!L>!sr*r?sV(Y0 zWQPi{2?dTDmN^X`Sx(azH5S9Dpbc2K53^Uz&h5nP3x}F`Webdi-a_2Ai@yk75c@x6vKcPWUKV=~Ms|w* zQW{pLVp3)mjR&uvuPl#)k8TmWY*%K1UN-dg`*9}Obq2?-R zLCxD6;9>zri{iU*CI*&jo!{x(pRkpG*ez;$Qfgc7Iuu)-{0B`wDFrIwMJ1YJ4z4*9 z=Uy-;cC$pE$M#+`nlew~Xu$E`sNX4!WGffZoKvuqNx#uI{EpqTd8aUgXZxLOr*R_b zk9=x&2BV2i1=RbD)S!3Y8=#bWEjDdmGWd&WTRNa_&jD%kvHs4JERFTINIsmHi1$GK zJvdezu=K?nuT+$~K}XM^`+2{JZE-8<@=dCjCykQaekXe#jQG~y=sLT@f6H!sR%+!Y zeRP9Ho|8t`z6#}oI*l&})p_zOOLDug*?_&lu+M*?Ij6;x9p-#Ue6pF{5eXi4-^JvKOP$W#X%}v^IUizT# zsujADl$JB3mUxA!L)lVhdbrJ>;9Qb&Oc4wmFoS`f*Z#%8X26^bG{2?`;fD)SRnM)s zA)J$|o=+DpNR3}PaT)Kz{$J<)7n{VCMX7<_#G%km(Tjq~^+Uw~KdUcO+lx}C0ewaA zf6rBP5OCL(`Gz_qGN$xgMSu-u)7xM%pMLp z)s0E{+YPs=a=VmzTHX0e39k3Ng0=12m(ZQKdWrU4m4e-Qt~cZt8h2T;dSAN0LJOBrxJdJ_prYNrLL082 z2i)r-}bzHUw(g%A2c?ZefS&sHGORC!-ll$qrU@ z9j!IM_*5fXIn;=p^FT7p@L3&6;l5!-LG0xQ?Vk(u^Dk0Z8&TO%3`NjtN5$J>qM*i` zU@aOYiOS={{_h}#_WyXM1XeCtN58M; zpQZWNc%K;1)s_6WERV9TNws{&>je4^MI_rrx^YcvXk&kGFs(LZ%nKl;2D8tKKR%IX zk8op@Mw~CK&kcb;7=E5KaJ(m%O$OX6^&fU*VG!w@Re0CM|3N9vQO7eKZo_?NhaIb2 zkj}dJdz3~v=vd(5pXGw{#04Je;{V14C&9)4yHv*9cXD>QU!|UIlE-E0e?wZ?;fqOJ z-uJs4F^8H&De-9X9Uk3a>=DdWVG0ZWrO_F-p{cXZQr&#%vo7wZ5e|dp2ZJTepS&v+ z#R7dh%2QDGhyi~=e!p`uV93F@tg_ioXBWHhIqYa&3Elhyr&NM(Vo5lPYZCNj(|PK0 z6Nhc3v$W?XI?kuDrR1jM-|);RK{Xs(-PPSFI;J|npenkX_J}GR_URdF`kU0UT6JhG z(_6rqK#n4L!(CJ!&HfGdBUw+$*30XmmoVsAf^%bL-JTe%o;gGJf5UE>eLs=k z?^27dsXw9WryLUZq~`P7FUR0bJfen-M<^T6aOTGt8@|CXd#hKtqQcw_xJZkCmx9cp z08??14VLDdqLc!ub*RiD<#C6Q)4T-r;VA%8{z%rROkwAk*mZot zp+E|azc5zFq|syKJNqQ_uu5;6An9U}r3gO`TZb^QR|gF3w$1qbmB$fGrdQe4a1_&&(LT99<6@9g5A6NzUS;}Cu!;uoLbK66{DL-Rd0-rv`e&rlJjQ8IMa!y&3_4Oik?{T_$OZq;cEuxib zum=+*A3Aq3Z|qOQg7J%Icw9p@ele*$eLzaBgcaq>C^#A#tPwwg!OyWl$(Taa+% z89j-o>a}Af)TAe-b}Bfa-vhZI!Rh{!)YyS3_Rc4$r$c(fE9Vf$!lnc7WwDgykiva( zMv7AHSB#|ckKz*yQdQnctsXjR(5rJ>3TW6_Wa+575xI11$KiLekxZN(7ERq9mMEIK z2FGdCZK`7m@9pNa%z*xibyBBQ5fp zdBDkHukKWQ2YYTK1w?eN{JT?wyVC1{%rU4!JPbw|>N5bM`gnzfk_G zgFmk2;W742qW|J(%iU%#2E&xcfs0_2^`E|tf`k>`_gJ^`L1_<5c}H|K{Pb05>B zKcvyNwXBbrp%NO;H76=0SX~Jw#FcR|_6b<;!cvQU+f2DL=CSuOcB@Lmc}VnBO+)b_ zyKGL=g;egV0s9zZTMn?f+NJ6d{yarVX`31qo1h4h_PMmMIEZV7ix2L6lg_%gZ)E_BZ`7?(wOOwTkZ zM;skS^X^Lx>pzA@vC8Otl`D(?oTX*(mAHpa-^YBN`%zNwODiK@<1l7X^q42^s;1Y; zedt=C)W5*#47CX~i&3x@JmLdBu3>CPs=8k{c4v#F8p;Y?!0KO|CvN@JPEZ^!zE^fr zxd+lXCS1;~M4-Gj*Hy zQ~m=f+&d0gG&+;DI#b|7bS7(XuF>Umb|!B}Qs0MC2ivAy(C|0-?{oY)dmEn@m-#bX z{JUNJJ4^kC9q*O;4?4be@o#kTcY|L)$BhHr_*70I-*iB}e@c@p-pc`VY(n=Y!%C{Y z`)K)}(yI0w!BOWF8wM;>oySv~>y|((ghbwFO-iHO*9PK?WZC+r)`&t5N!+_SLsn?^ zBQ!QD7ZPkj{C@fb@BOy##=HIFV4j13*@Z2CeJ3-9PXh)B7&P{&+63Y%QO_}t~U z7{o!y92&lZY3$9=X{amqkoRLL-KQxC#iZ?JGV015^zCDec7GX2#~)+P{?I_W^O&dQ z29oC!?A7>uAPPP8$e&;N(t+fwriJ*R-eY`wfT28a5T5g#$IdeF;>$NH90?=_J2KLM}p2U0$}p#w={*MA@dJ%#&X07bB?4xl0I z{yc!@Je7j${y3nzi8GX|m{?%n;4n1H_o}F6DBXF<>aRN~_o?)g&CLmm&fvn4gyj06 z=1$LGgCU7(FfRi`yDWW+vLA~a#K!yp^_Q`Gl~1w+=ymeD{-Od6y@{e%p-M(k8im#R zduIdNff0_P{CCwiT39>B)W;=RLI;rmn@s%}eS#5%H~$f9<5ze@U%t?dJ%r*Lp4wWV3#hdGC>i>>df97BoC$rat1ypRr1K@id z5X>v8?e{*zF(m*$&Z1^7q{_pW=z)BN7k|b}51b}|^O6C{*CE4oNCqGt&~Fgv4M?m# zJM)b}n8p54v`>vVBlhfLI!LrN)wk1^FEBClU>lu!A=QvBY$L}DY`MtXMpZSbjWlT+ z#cL7;6>c`_x@|sqPe2k#39GG~((%o!Epk)O0YU|is)^aFJIYl(+ZeC$*{k1_YlKSi zLJ9U>K^ezvWeJFn+o3Lf1CY}+H`xly(Ax7WXc6n3&kw8f<(8f^jo0)Y6yzrVEQM{R zKi%Y7(#)+?RgzmtXTPJK65fNhQlca`;44no@q1nt?UUp%sl|76hu@R4$VZk#YZh%{ z^3lmi0&IkHW>TYZxLoYrYMVvqS;PIZZm3-Xgsujm@2@4~f3x?IP-%=}gd6gt*;u=@^_Xa^< zbMpGfUiB*JB_JJR?cMlzgYQBGa{}tqujo=aIZ(R%6)r@TL%VJM>g8zb1*9z6A#^6y z_ZXORB%x>9N7MJA{<6$)ClwEYo~q-%qLCi*l#1EkIXPriR&z45i#+5uZWSj9aU+jH z=hewyQ&UfQyVUke7I5{DC+gBnHVR*gf=G+ba9B}q*_b4KtIMy^w^X}=Tvv+Dq}U2_ zJE?poEn@f7*R;Qaj63$eaV8we34it_l~jD*lCWoGeW1YX}P!DqUtWN$fZ-8U84;d{Rv(6mIp{fzNF?pa*FrYpE@0Lj0maX%8kh4cLY=ETteJ=b# z?2mkV0Pz|8EzXOVON%PWlWeoTKxx@A^UTLW=YGT)oq)r3_HCEZ>p<60 z&0Nc{R68*A{K2_v^8Wp+F zpkuR8NSvSjD1T;pC()uR@-*dnb3rcRFk&8K-AJ=EgCDcp4G&Wlf4PAVhqUJ+29+-| zsE5BCEYh|2zQY}R!ZQ8kMwOOuW?cH50|KeYU+!o-wgxIunegX>Kj)BW zFs3J*{m+&z{x&ZD-Y)(C`1Sr|=QsFv@6LVod%aWtj9GAZrWm1OW=34`&AWHwLfRPD zXVKbTl9w&U-res=cRv(jxtOEfc?uHVOFRG@6N3R+mUxc}8NizbGx!A?2s7dG?}#3b zb1xY)N|d(HCZKVcju8_(X}g6&VU8sf z$hZN}ci~?2Zp5vAJhvr~7VKA9>)M|2U6{b1rNnJi9{j_PZ))E3|S35aUROfWK356!|G-r#-yzj$)}Z8mbD*>fst*3l|Q40eGVqyh5M1s zvfX->KhXs`2inY{O9pGar=pFZi@S)_vy73p-U!(gvV<|(-tk>1zGj8dm`98ypf4Ci zN%}dbe|g{q62Ge3So$`+g~D*FM}&fk9WP6QInJWvz6)zXQgLY`un5;aCKZG&M>NsQW#xJ=+|Y`n&jg97s(6Ha7Ko&(!B)O zmJV6vZrxi5Ne>B`$)B?a-ltT!)H7rdBUz#nO;ZtKGr@RyY83jy2K|m zaBH6;*O3x^Y4mKlflZv+Sb=eZ+Hw`7guy!Y!TK)3UOORhA!sb`B})5F`S(hW>9SQ=U^}Psu5lF=Ba*I9< zlmp^c<2#)(M=`z-9Sq+^t-v-);w)~K>xmCX+9S17mHor-T7KO3`)?y|3~s& zJcUOzJcbuDbgCzvtR)A~x|(tm+n=pi_jQF;i%=S<1#zj{^;(`bDiX&*W8zZt7F@YhS||ljOODCa|r&%wD<8 zpW>VYtlt!*>=9`>kU>?UGuZbgB#hmHCazibh{+uI_j1wRh15g|I@`NDP@1y#ZaQ09 zbf&Jaq*@_zm8eQkiX=XK#T7s_25Uvbgjyh!9Kz$;VCYR{cwzRhi+e!%c2jP!5@=S4 z9Mt;98+gs>2@G=ITeLK z>rnZib(rG#m)2Ebc{sJM+PDu-l9l^)2is9i3p3kf! zYbsnLYk$Iv_89k@a=y3;NVwxiE9%NY6-zM7;;Ji+DYvd%tuFS9{KsIAg|ImrhQY41 zjGot(+tS{evX||j#x7jn`{N~xJrNdr9xOHvf<0r4{fFB*S zwVIq9Y=_1b8;}&@C306KhQa8Oh}?0HB*=^MIDSPhI#nHA66br(#b#$S;_+dY$9L_L&ktXmk;Jfa^nRJjf`1vh(}*8 z7x%Kxl?_y$V4!j&CUt>6LRr8=gwm$Nt~Zlt=p32%_{!~?EL)S&qx4<$1%KyyFaC^c zQJj6$G#oZ@OfH2RO+t~nZHd^#xM(!KK8<;*l9;xaeeFZ>@~aI~MXq&bmPN77K5`KFwLAfw!kB<0)(;jbDThi^gNd4cS1_@Qu5!t?B=}O z#GlQ%t}nhswAzS%3?U-HAK~EyjRc;k(+rF!j~F8=M3>fGyuBo?Zvb-S;ZF>K#I)uU zwUrS&#~IsU+bmGZ5~%D<0NV*&65wyB?nH;f#=Q>QFzvhS8-N^nV$)$1OCR&5Pt*(0 zJI;TOGqz*1z|iUQC~KR6(GBOiV(eXQB^Ya&l9{5t4TJuj$de~XL;)OEw_N4u(~amJ zdh`;91`HPo-BbG*7%zY!GEkPl{r@J=<2%3{KjY7s`SmxV=Q^W1cEHCA8OD50BL%h7 z9?=-5-_)E%x-G(GZGp;W`n-wUP)c4zr<=$Dw$UQ2v^%Hv=l9g3&PqPE3gUMWu>0!! z!aW?<_Sy8$F`={WJ5IuX6+3*AIc<};a!c5=2w1P=c|0ip&I0R&Z`*^Jalll+WaURU z#T%}pc1u)Er=~l%G(4yySdU=rV+)yeaZe}+G-S{Z3-yuzDVRlPPv}=9Qq~g+HY z@>*0A0c@$-I9Myn2vuab-57@;+>b|^F^--t^_oX+i}rwTjvwH7A%dWy0{)Q!_jCM+ zSyMqb#%?qlF!tg21lBOU?;WESEMS2;+Z1sqk2z!zHy7fP;Z`JEv?9&UsmmA8#8T;mEGbqdFL#9j^&&90A<5VM29POjkL zU+nP62KvhtWU(N*Atafxz)mh)$8TUKy_Ag@5bJk8`Tr+#f?C^`sEN!?a&9(pG8l<0 zgXa2Vs@Ytw*+i_M6s2(1%J^U$M+X>#GCo2Pr+2atN7ui3ch-j@j^255&XPD52?G_0 ze&)HPdioMx3&Y%x1wI!tnrPU3I@>}H6879N5Z~l>D!;RxKr>Oxh*w?2`#+kATf%5L zOAog!fO(fCM7~~?rP)S3^Dc9sBXB<|)|T3DjI+fNS*`-jcG~z`YT`WS>VSVV_U8R- z2lB!v&{XGM7l#8cW%1gS#q<78ykO+k8PDdZj5j@E=RMp{7ah>eqT_-d7~lQh;F_9> z(&vK%YXEnw!XGP~3;v5cFvaNCV3d7T9ik&Ix(gs8J8r^#3BMYw4N&7!ZBLnem_gnR zV21{M{trXlp^+kj!2idlv(pSvM^nA-pvHFIt7ib+xIBo18A5%(t)A4;7wrQuw!t5c zZEyucd*z|d9PdC=%@H`q>Utx>25!h3Tz7nEwBtPWpFf9-Fq#eS52lxkq&YSb0ZG4G zweH`P&|0qJ9}I19?J{Jbu}`Or)^f0oi=6F==qzIZ&r_m~>j*F1vwBNyg9ME=Lht`1 zDC?)l^#q@=iE=ToPEF@T(sHqQdAYOF83wMsgfT!#Af&ALay(2yr*@M-CvO~MMUGRiiaqgxWZ553+Z9tA|&qeOV z4PQ(6wX)6F5V*aq91xZ+Ec#LP8H)~+Yl0qhF`em(E9CZ}pm54-7}3+Va^;d~@ zr#^ZvW&N7JgS7boQ3Ja~YqcopEt1ZaGYPi$E^e8va2o|CVQ(uA3^z(PeG=^J1AvLelXl#RlpZB zydvN+Y0lFR(-^c5+1iCcIipTtR4#|Z>Mh8Fo1fC-mfSGGrk$BlVk^auE5pw*@Li8v zGJXc&&g*LHm!YQ`=rN+b+peEp0{Rq2H@K0@&<7dlV;J2V!(*J+6zp`Fq04JgC%J~_ z-q~D2xa@a!_Qp=~pKewCrf?>3Hj4Gsm?e0gnEicc4lFlW4;0Fbz)%cs|C~g-yUN3* z+$j_kC3ll%PNC6Ja!>vk#}85RX=z|0EsB==Nm3$Ri>F8ef{(O>SQG zA=9*D^v(&|_a;NE>aUY2x0~Fx)=n51*rrMZp?^GyHC5lw3)qV_fTdD#tXzXSc1KRk zLf4L}6Qx!)+-d2ZdF!|<_PG~ zGNL#J_wHzF6elN2kz?tTIF#kHF;oMf6!@Bctx*LTkT?Jp0JC8ccbc zBN+5UO6mU&!Kkgu=(ih5ef!9hmCk<&fxV6c;_CI`9M#fI92WQQ^gi9_BZu1jIVhfG zi9*bQV8HDlH{L{{sk21c4-uK+Z8{C~1c1@_1=4HxmWah$BRV03V;mhU2vj!+v=KQH z8}|2h%6hC(+1PZzH+UG&xBC^Z7d25n5aCk5qz#7Zz%oRS8gPI zK9s!r$x4ld22L_pFyM^AMnEp32}7w%Ke@g%Vib+?oIaeNITtGHtfrW^cqRw|5nXlJ^_ffHrk7b$CNos`q6y5MagQ zQ`4DX24aX9OjF*F{j1kAg7Zc8_lN~~1p5xAPZ4Z;Hb{@1U<6;*W8XBukp`HDnTU15 z00$djp4A3;n*lZ%;9MQN-T-IeRn?qTKz;m%o@5TdvZ}s8tp~`*q!)wM48%6Om^Z23 zKsi*}Jc#1?{n=2OF;K2u^S6J5Z09Y6AUy;rUTd^ROklv%H}zH~Zy;>*)C7=+)?OV( zj|QTAUmHq+gXCV4+fbS~NPfj@Et1!_b56QOS%c(8-U$N2Tlc(MT_eXJIm|1x3{*nF zgXKqFq5YX_9xQkRGDKb@b;G6bL%?GCAo_I(Sbox9qH}3(jl`_`&B0WfuKad>#Xwh)FllRPcMi&E|o)_rsaQSKD z^$sD&p177#y$ouim2w_&zVsCPWYB|(Xu`p%{dB4NjF4+|XbFL^RM$fcj$2nthc&wz zqZFb0cU3|6)NDi?An025!w(z0Yc`D>A&2;`;-E7uMUZ)=KkiSLYkDv4<;;-(;GgN> z2)V9zUx18JS%aVH@d&w_O}PQvaIy#B_6R@r`}M|<^x2>;v9@@TUh4Lb@8WQsz}EObgM?&81a;e2(;@oYB~v!ue08u{)tT0c&1*s(tctzfDU z!e0=W!-HoJYGTnLL>K9X-vo`ujF|JPpixVwQDYjJ$IGFOig7Af4Krx0WEu`k0O*5U z?i>_%<5>7AssE9mXux>6kyj2NdcSVjPm~TwrDTCqcK9X!CptYI`?f0=(?8?o)Xt#@ zZ>Fg$KwV5B;$qJG>PpC;r((Eq(Z6T+RJ8%d?X*5#b%?c`duoH}ba;Yn?=uL(;$l9~ zg>!sg-38YX?VPOUuC*Y%4YGQf@TV+45RMn)Tqog;o9N4lGVZ6kL%k-UdYtM?Hz&yf zjaoobFH@+=(gTI`e^I!CZy!vSH&h(~ZGSmN?^wDqS>DxXB{cozFdJY@E&N~9sxPL) ziSno3mm^Ef{&$CI$`rI`83M$e=^2M9bBf$vN{yz%DRM_CHk#^Agj94py^+QasZ<-d{qH;n%V@n1juIqhH=282#~SLQ$H z_zS~#Cr+nQoP!RB3;eo^zpe|;DFGj%&#UZoLHf?c|Cx*5;u1O41^(2?cBKaI$Pv<4MKtCe`6KC@c4VF@PiuYQ3h!q!43S4CU5nCRfs5`}KJ-w(b{6p1CIg^DrD=b>J2sq>M`M2*q*KqG4z28&aRkjZctu2(2zQ$nyX9In$R1m=1-(@#`}=QROx+l zn`*NUVQD%w#bfYba3c2hd2jgpW;_-=?s&@K@xW6ak0+iAc)aj<o7lD>;weB<2^;S-zh3 zjSJQqo_7j>1!4Copg9+;!O|25eSE=cl@^|&T^Fq5+J;Uo0u@Z<>9^_6y2eD&{_xOf z2vYFP*0*IJ?dk#LK~`^!PVE}54u6M+UbNPiLa)){i`J&z@BLC>bbu_?*6LEQ~np1s$25ENv7lP8=JvCiaN(Gbs9+wVhAkRfO56C5Ud}RkB~R z){q`wp^ew99c@4SrW4>D2xA$Kdtvwxz3ydZQ{V-&;&5}hpP_E}R@`pRl!tm*BpMeI z%o{E}cq781R=meSd>!|`>JZZ82{&NJtDa>vo9Z;xY}+|jN(jj4>*8t=K-l=lbL|PZ zz%L4Vxi{3i7nwWpsn8W5Y;<%rbpuDx<$47IV^;0!#pQGAK!er*{=gGR{3U7`ruETD z7PIaW6<)W#FGZZEDZg3+hfd-oAipebOHe*9@|Yff513=;AvQzDoGs8wcQi~9#nn%P zlIL@5OzGvYnxV;IDk#df9CqlUVI1Te)*5v>v0#wBuUR5!`UF4XHmKs6zo_s-Tv(x~`8{l*uJpEk3 z%HrZG(wpZfKHuu!u)Bd)%q*kvnu(|_3|O84kPHu3XPOe8H9W1oge)Sza zKFs~Jp&+*el?2q8oE;%d!T$tYNX!pvp=P3J5Ezx#MxTC#KC`(9R+nF)rbX6pu6@Ic ztm7rWGjzJhI!M}nni}4+c9OoBMB{H+Yloa+H4*Ipj8aqcSy%M*3K1gMKSo<`p~<^@ ziO$^u#gERBSp~(3r}P|DKBebCo{0NIthGBd)kz=+_udA@$Wx^hqY=UsPaP@H9LdU;-1gOkXCu~hz951Mz!I@o(8Kt?{=_MpN$*1F!! z%RuFNP_?_(&bC8`fMt(()*tL=9u)q&?7z#X_K1A;=fkhA10t3J0XxaCxxiK5159ns zfAe%QqhCYN3g`pSK0+(09_FYC2*l*CBMO}mT-Q-hI;80=*_;jkK}VES=C2}``NLfN zVy~x+Hwett{c&rT)W?VWl{S9Yad}2OV2VaSl5E zDTN<)bSd>8bQHVzAHZ+ya1fp85q8VG-%Tc*^(*0{ducZGGou6ab=^HI)71Mz9d#f? zh+ag%rwRVQ@R#cN>Z8LV-o9{{=b?@n`>D-6Yb&YKA)0&-wI=8grQfp#O4>o%a?d(j zN;ybj_pRLn+i~IJ!-M>_fSZ^%Xdh$m$|s?dMyfRr((?O=`r-g(-M0ov1qbNFeULbO zfE@R&E2Z!QG{4wdwMM`JkVxB&UNY1qC4e2Vnr=Ekn-MOn`wOV)JU4$SZ$JGCKzz=A z5n%}!CaBO+u7_?$?vV61U3(;>lth!t*&I#)p2qoV>YZzTB*c8uFkQ4g%qHR|Y8 zGjytA!b4E4u%EtoU>zfUmP_6btAWo{E_ZFv{qL#5n8%aDs3JbDF5wJ&y4g{SCWFWF7? zo?3e-?O(zSQX3eUwRV&JskNHqv75dEW|Q5!UgmkD4k=AVQHdc)W%(|u`ONAs&D@pU z`k6J$O}e-@Tm8$bxk-n2kmDb#B7MChyWDeYGdC&ehwOGG)(_mI@E_>(3vjk52lqc% zYfBHdledQVZaEaH!8~Ver(SrkWyyi%LrWWuvWj$!5?g~J(mTR1?#_l`?6#GbXx0`r z*F*xcXB+sjM?`aIB0}MB%l?tsbXBu9=)LiKktb9U49w8Q`jFqzt_NbR^9~nhb8@mGUJTOM?YKQ?HvTgP2$~@_h9Y35^{N1D@S){rto67BtK!U$#;XVi@ zP1^B2h002>wCa0$RaWXtlBM-qvunF6 zo!q1z-_nS3%2DavZ?YSCDDB)l@3aP66~8IK=CSZlX`C!=Dxi-;`6ASBX=s2lS;{J) zHycP>s8@QkXPGF3K#RD`EH| zYept@^j4-z<-egHyp<27dtXz$kJ2Y_;Fm1lXpDBSgH-IFjmB9av1M~}Cgu7lH9XIK z!6^6D6JJn)kJ4V+`xVvlRay`Hp$YiS|GGdE9}9L|=XP)SXWR%rb?}`FdTC%L{Zl=D zUC>b@zjHQ>ht>0&^Z>671zPEePt#~4`v<<%voBA9=U%8ZQND>>2?6xpUUeZ~@~LD^N54uRzbkN;B) zZ+=dG{z{F2cRvQVFh;R$UqCOD_zgmt@G*7qS0bdL8MMG(Y2Bk=D1?#>Dd<8u!9sCc zrwb+AMJOMCsK-CN9zx0gs!S+J@H62}ACpv7X)33ERzN|Y;9~3es>&p3{-=~%Rp}v} z{e--$DG>p0fpi&DefbS>RbU7vbUzLxjoe z3=x8DU5R#lWQZ{FBbsDYlH{uhnbAQCC2vLfNLu}&F35w55*hf{8fM{t3bNNn6db73 zs5f=B;5jn3?Q;lnr2b}zwLiZh2fbEPLLkK2X)R6wE3JC935HllKxXJ6=#t&RlD+wX zE?K@?#HnucR_G+YTm{MIeo`jczVI{crK_oSkPEIf&)>Ja3 z>TBq5P3ZZx)g%QgG13RCDK1!fTPpt%{Sd6EQm0k)X)Wb7>F!E;SPPcox0Q4~L{X?s zZKb-DwvzhPRvJhND`|dhrKePJC7r6RM=z(D^$=cTdG?`t$}%@; z-16+cp-PyWw09{jXaIv$@qPNE0XP|LCy$0OJb9_qq#@qx+9?+Atvf9d;>XcD7JoDS z4TZs4T}OWlX6wt#MwR&;BCD{3zG$fQk&51@XANQecDzraVM<>q;eDDPro2b_^FZkkhd7durK9%27>EOM&uBAOJA+J9v+6^1K?($s~z z(iSySA_A{0;Kcu@(l%K{k)3rz+pA0-l3S=Z3t4CVFWH%QBzOy4wD zhDaCRC65+LYujlYyHo!{&ancfZz9)Kcr2^%lzF-e=i$Yv!rpUrLal6&QhaKelnRXU zP>_Y()}@A-ML?E>f_FRJEuPHS1HEcxG&&+;u@61q}=sTeaB^= zX`xi~+!3kNHP?!p{C3pXX-UH;jTjX_b#mhHw}&TtU?M~xmebrdKv8B_Gk#L1IJ zVPj;UZb}jz>!uv@n=!@eoo|UkkAQz3k=g0pmHj?6sK3(Ot#Ni*f2E~cm&_Wsv?bMU zX#)aoX&%*YX_xVMRK2AQ#+G*HlZkhohRM{n=j3U_$ByqacA^tPf4`wLv|V#InXUqq z)xALT!*QAP0R>tcxLI)H;UHLA0C+qwP)dXw+00~` zZAZiwCR4&PaQceL)C(1HdpncqJlqNGO{Uf`p~Y~0U|xrGz`P;cV{qrLgk;cpS_>J|2W zkFsTgaFanO_$EZi1mWhu&4*hI*YCFi&5IL&dkAhK+_})1EVygoCKrJrq!)j?z^0jz zVEDZPtuNff2L;*&X5a}3f`Q;?$T1km`Wsap3?%*oQ9`N0pQB9S=9d5;ZoIir^MjHl z!VQ6&0k;j@Jh*Xivn++$dMIC_SD}^_0JjR@P(o8JOg?1P07vx;wMTF>;C6sACcFZ8 zFc^p^)QaJnx)o|mp`5w>3biN{QTU)jZ48t#{o6wA7)u83LNF4%sZh&7f~M~ZH4of8 zQ4BW}h6L^uYVmNB?-pvIwNd}G;K_$bi{UF12@CHNL$74<%+cPaP$0%w6zUw;HYwuHlYy`wjuy-9$YgFMP#iaEs@=@B5hL> zxQ(%Z2g4EH6bZmhXjY`{f!#>&f%wglU|f-Q3~p9Jk(SjO38ock;qAcKx*|=5o1Rgm zEri_&&MneBU@uIEinJsfJh{IWY58z7d~a!UVK^djMoER6*x;775C$X}?pnCT3pA}| zC%luUzWUSS+NVt9|5hR6V1 zTgxyIfM){SgikeXJ>19)O}oZ$xL%M*;%A!H0j}wDO)F;i3&0@}zi%`x0dD*zO$&x3 z61HesBHZ9@nl_*r7}~CB=i!EDgYgy!$9dI-aPxO*nyDq|?$vDCT6l7QL|YFxem@Rp zwL%db(6nQ46AmK*h%)~u;IDw86M)0bJF97P+W`Nfrk#YFcM0>WZGn$ncKLAQuR}tR zR4&|rNHB~aYMuDG&3@hFHq+0|>Q&Ao-Hq?fSf-jmxN~k;CUjF9>UR<;z_`;;L`<4L}{%L8n}I{Gz1so`GC{`K@CLFrb$gN%|v8}~N34Oi;XwBbr%N8S}*@Ogm- zQ)Mzm`}n0uah^UNohxwWHy~`lMRZFzERMt87MbU;T!hWNNT-J@Rm)$4KMQ!H=(7b% zB@ry-7j@Ak*C<|kG@yb~wSUHWnn5_uw=Hs_q>PPn{ zD*=@9meNwHIG1+5rPS$kXJ~;217R}%#bQB$;<=01NlwZRz>QRyGOrg5Kx2F!MQ1+S zl5V`C1XKGFpg3?2O&OuosgVGRPl0LPSw=C#0;(5i^9W>-PwM)C`Wd>J1a5jxQoQKF z2<43myfl9RUd^l6=*lT0KG#UM=7=F;7Fu(b{74Gz}jbqpw(xc z_y<)Izc@UNKtJkQfp(5b{mGHKd7i&fpuNKHXJ{GTD;z>A9t}M6*DdJAC?&Rn-<|^P zJ2dC!H+QN%&R4a~|E5wQ0y815mNXK|xq|?*g9t zA^klDy31XeT$O5!Rhqc-r4Vrr>NQqrU2ZP?d5!||oukw$&yg|#h@v0HDm6V@-YL-D zaz|QE>DRH!tHazO1+FLN&Efdh>r6|OOdIrgstSk>ivcVOu(~d=A%G>gz#1Ve3H;3k z>{s~BZ-vu)6_d&`9l2OuDsc`&@k|z zCU@}(wwt4ULYG>ie8LyINBOi#DHr9FAkCrRB*ou9x`K(TVmNYJ3<9^AzzKRdPH9q} zdyyMHEHtVhbr`QGmJGnI(a`Zqci&<}iTnt`9HnYgsy{(#P??!&ge)c@U?T_o+JtNq z6st`d@97g7kDAq$3}#L#-;plnu!QYK$yt?$;O=j#$lTPT;+_gsw_f0A{;|lCc@@%{hQmECcm#( zY2PHJUQ^Dx;)ASb7)ibU@0e{6rXozlZ08cw#xa*7w8{n}re9f14$DMXs59(YqtXm8 zKZg+Jh0b~ot9CxZ%9JL$RB1YwDouBvWJ&%*^7Lr~SZAM5C{`D0oTPZrmZ^#*jMZ}{ z5b^d zSfwgOELJ?-U-ij%ldWBkHgd$@lrW#tsd6Rss*L(V zvl5m1J{>Be3EEhwNz5qG=0v5NPdZ@57#0j?W>QF+qBQj3p~V3ALTwg{yEnC)q6EcS zUaAzh-?zHkzpI64hyozpg1(yraYZ$W&!vlJds#LBbEEiZ??B1Cz zS9hOy>04T`MDaJrRFKXHpKnx!7*JOcu>d2ZUbJ93B6ce^c_LzzPonf#uv---FAn%^ zkg~c5;}Wj$gB#HDca#WE4p@ka6Z0c2OHy8SKM#K_5c*s&pEDUmTV&g(`*G1vG@_PwUf}5okiY&p;CzJDTRrKuaCkr$AeWRLtw@<6o~I z+YxI*NTIfqMVv;zzN6HWx_VN08oC8RGZlZI?_gw%exOf=ELy;hOy~rQ`4^oKXqe)l zAn_RV!3f~R$8WJTMCb{Z;{>po)S^(EWJa7HIgt=ql26cr6`1CHJd*yHsnqG%u5W?% zITM{zM%0Yv@YwM}jfX!v(XoOk*9Lrc*0gkXfo5eP##66ZSQi>Tk`~NTs@eMX(>vnk zsyeL%;HLvWw{@X5>^0z*103DM#Zp&q_o(IaGIKOm!O%mi1w+n%M(L@&K01nTb7xZqjrcNXF$QQxA+*nH5)aQhr-Fo=tu~_)P?q?p_jFLw$js`$Hqw~$Y+jH zFX9pWnNzj@h?vFi7lh6;!d{kCON2E-SUydeqqMM$gm(aKoTCi09D{cxdCyg>byRrG zKViJgspH3GWQqlkfU+Riyq=2+^2d`?3oSU6%vY@Lm*E|Gm4a+aJ&U05e~w7dEAx@AF{Tf$N2uJGzwSxcY1agX!&LrGqqd zD1Dg>9yYy+DJ!IF{)77&IuGmXKso7VvSRhk1rOmxg<5+FD0}PCmN{r5_D(_Xyzv4^ z{<9%8d;zF}tfzqN}I=pkIX*?jTTfPIrask*wmUor*7E@iA zREmCA3A2R5dyS^EHv!&8^d-E$tH8~Au<$9H5%;=u<6UK-`!j@}zegQYl&W>AAWe_y zn)Vk6^N&lc5fV6b59(_{q^TiveO4Z1aWF8<^oby=*I;NfnPrkS~Ddx!AwB)a@U)Z@%Knihc#?a


#@1@MAWIApWBiO$*^HHLb-Z6GA_wDuI?vSgiB(N2>CUdk9SY<;B!-iL#7x zmns$?q?ETr)1o-i{hE5DrfG=8lRJ6zTADJ>1Dnc;pHev`eFfZ2BmC_Y<; zPg*dA9zi;Vr%RPU-^(1*ph$CoF>}ozy+(Dl!>FXj(=5AEColwEq(8W%*THJw#}eVm zqowIk6&7&_UAHT}Eq4J6re@2OEj}BXBDWuE+Eg>5ji-CdlrHYY%^=8+1%DQvg-fQb z%axVB9stk8^i=_K)?Q)G>d=gICCHa2rpCNhq+5DlMd$2bIyfuelm1Fq>U8=5jnHCn zV}8L_M<3P~WAJ)yrtRE)*mT@Ke*{V~VvjP-fi=(Y8(10g^;&5P^ck2|} zz`qHx%%h65_h9+V-_ny6N<)8?mH4?#=bY+6wPs@+f{vJ&eCY^Mm*6*B*$nF19}edH z78Ys0vVwUjy7d|Ufzq@->(w`i5y3Hx*&=3nJz^|;uSna;4M?$I+3F?6d9V6p$#T0& zqT55CzJ*S1@HoX%56RC3op3I&cgs@tfCan!B~k|G=BYxMR+_X@X)6tUl{T(~Mesw< zPPFv3(8A!ysc%3mYk|8-!c9y9X|@GJVN2l zq_%66u9gmM(MD!3Sfgaio}Rs@9&s~WaI=^w@+0)o;y=PD2!G4Qk9-q)lV~aMGOc&B zU{t!*&64S5%5$?k_cDDiSug;-Az7Aqo9;`NTrblyGy6X@TUL3SE(!l{X3I%0Q(-wC zXn)|rprt@x=tG=e2 zZkENqrUJ=w+SjyLwtV7iS}j}t_A#wAFGT)MSVkZ4HC=G$UCvbAvcuQ3p}eIC|DKi) zd`(9@Ef;-E7d$QB_?os=s1M9L6^5BiDc+WQKBiB+kw<0Q(sGJHB*5f0y8UG z3ags3D_Xv*W;#;QX4zTIbhV=8K~>YyN(fD>YFge{EfPKvdQDzi;3Qf+hpXI5H1L%_U7`GjN4hGaP-dEG;1ZTun5k_hxaSsFTA3wi?%VI2d(PvV^XvTa&b^>V1HJ>IWBbFQ<#qW(oAW_#;SW z*Yx`!Sgx#TsFt~|QD(j80A6ayS^h=^D(CylB7d>RACiVp8**KV>2sq*rV(*FQoQd! zZnY`01LZG~Vo#u~h!mFt{opBcd3AZn6n|BhWu~|uB#R@(ieR}mQWOWvEs>(MhP-Zy z+co4Hkz!6wnHec^YW7(XDV9Ib_E@CIs3kv)5=(0}T@od}t~J+|7bV^el_35(RDK_6 zY_HR}2SB^SCB)Bm41@SP>dFhI$Z^U7Q!K29svp(Em{%e&y~bt#%oIf~30C`E;h=fJ zWnXQo;+1emOIZa=`j0DJ^U_NUV~>$s7;rXH{1hnPGsQ>MV<3I2y4)HmN`mChNU^P! z+<;}0`BCC(EtwT5mW0U4NRb~>dtQ{d7Sb7z8+O!O8!8W*;!LQ#VTx;^b!J71+%S13 zQrxU9_eC1N)j=I^xco6vmhpx?f+$;E!q zdrUCKWAY98ZJ@~Ulb;8QO@1MpJb~hSzmPS7;%7g32GaiWNT66Pcf{y9=7Y<_F6KP{G__c`x69HAP+q zmcA!g{tEnLusi|mVzAr~Y*r1q3)s>cvIyAv8gf0b?3!{Fu#F)){LT>Rh1|XnIR{u- zh`a@ja3Mrq1a>b(&V%M!V3&7t4YATL_rtfB5A1RmupM?;1ne8TTm|f8x?QdZJ~LE$ zfxR6n_k!WhP`Lrv(NLKW?9Wh{4eVH$+z!RR9*m zzunG-xzF0kb&z|fz1#RcCWiE2bSGK-T?MSy!;W&|A?38 zml?*6UUC-XzUd{?vw;6e*&Ds&LHM3ko}h)td&{37_rVkS#!pKOvAwTEb}exz)--#7 z`~z~U2gqx{vIc5d&R|`Pje{d+!Z1HDSiTOj#X~fhKO}M?#eK}O7 zF9-D9;acb8;gM?~cYL_q3vBra4Xzszc@T2@M#%GEQTDV3FFq}=LN0ft{1n*Qk#Y~P z%_HSP=#ugzc>r=1N%AzXZ7Fn+^IBR>4vy9N!Mxqi*h@(_u?1z_$qo) z?uFc{$?{jQ*g9D%$nBjhPe5+(6b&AkA{PL-ajLuw;GL=R9f$Xqa>EN)yPXi$7o0-Y&l;D`6-cOxL;N8HSt*V{pyuhR)~C zGR9)Rzdy&2#}*sL)wzazeYs)0J>QVap`Mis3|)x=SVcEMcYV4D?!Vyf3*b0xz5|Za z?kI5VvXj8Eef~~gWY|9kg*P+FVHR)<@HTLqt~r^;Y8yuWVzD8y^j|GDg0O}MA&>a~ zZVEXM8TGr!+ct5~2Fv;9b>w?aWgZ7Z9fDROQn&RTeLOfNTP8Y}$v#fW46q4{0JvH-a*MjQ^7XW{yQyb~kJYsnvD zL{3+X#&XRw)box z-rNy0`#YiPiB4#}ursE;og)F?))@=@l}1WBqw&ek=;*i3CP<+X{3jN@{E^GB!E@1n z3tfHdU5A%fyy;eNSF;b^5b=I%yb2Ha&5OZ%eO+Rr%SpVNsR;sL}oUaqwV@WZ4gay@G${zrmMvAdus} z8~lTvM>VT5IH^3l;Rt?*c51+G*T@EC@T!PZjhKiHphOVon{-nLcDo)mIw<=dS5*Bp zd|wA*Em4t1dDwl@l%e|XadmB=ztjQ%N028V4sWQM;E&MieBijEO?zCw26}sCPEdg* zu4Cy|TvpV~55idGyB`k}f#d#(P})yGV{?K2DfJUURRz5t4;EY@l~n4AgF%*G>S|T5 zV&^}#EZ=qkZFauY)v|TkP#P=$)bfMx%85z;hSz};I;!^p*I!O+OzPttV2nE;2E3m4 zQvDCQ9C6V^f|EmowNYA1-(7ef-o znRhfQTs)FW8L#yv;joiK1aj1mVf-4yX^gkoMF5^DK>C95oUbU4hX9c9H=^JtUHrX= zfOukJItfI_y#&NCzMgSw2E(hpCacvFxLG)^@W*WsQF)Kms#qxCSONDy)P&8=ViwI} zL75i7nO?^CF`hSwTo-VJSde3PCH``MKMjC=DGV@Gc@9GZr}>CCuy{7t4_-Sp9bo)J z#!oRG2a6iIn~$3tKxO(0=gAmcM`*5Wq2T$s$5Ffjv@i0O7UwQ9g&57!4fTql`O(#^Lj@WyA&rY=GaMknm^? z2KeuO%EP0prn8J&Ycy^gAz3{=ms`{-Xb7w}7#KGFj<_5RTsU-rV4F}=ZxCacCm2tz zrOqF5HA%+r^+2EKs}QfkVu5Pzo`mafIUuvTKl3rdt?us%OCsujSVj)4@tDo{FKXgZ z=>7raB&O9Dx{t+U80Ym~v=1hCZ!m7n`Xt6zFy55hiO(4Sig6gonnG%DHO}a4y53R6 zWGV{^W>P)=Hnf5`!uV1$5DtRH6E(?E!7S3pO?9Ll7Ve|p<^j_G`aT>=nahGQm37Qj zx7TX&GnB(SL&)s>S#p1lSkZ( z>A0(Yad};;dMzMxAiYwhiy7&Yy5a8fmKf zNf0MjQv*)ATGn&_O;O>oSkue3g=hd?5<9BppyzbKQVWFp(MYerW-E#_Yp9!GZYz#Z z%}xO?2~@*Qxq8+U)oCoHlDhE1*sTvMS%;zO(^IZihE(T~-B9&TyB-ZX^OOJ?1iPU| zodz!%SJh&`)0;q_hT8CUPD6v8iE~bho_vkw=vWpkgs(hUs#p(2KgN|=2Wp6yTqXUt zSbx8THz55K#uFeM=!c5L+9be3I!Kw`xCb05?|~SLo41Ml40M;-M1*OKUhO@ zJK*(g5u$DxH6pCJnhvslSw||4)m8Q3F$9K|_h_))nFwk0>06^`y`{kp=SwWD;00(M zdtQ%H&k>foxeXh$^oHfL6UDXgaFt&UkLOQn<{9J00aI6Gd`G3WX8$z6vG&Cy$l6-G zSCU!x`c&ZL3hILO9CRq)=q``lB{H7roe|(Lw&-gKUd@ILNV9@9JFsSF!0qtH5axLb zQdoqt7pMq$3JK{w#-o#MI*%W#k-k=0XJGnY1~C?)>GxEl3@sF*t9NG&hp|*&H{&&7 ze?tz?j~qo&9PtO>=pmMi=4KB!0mohvJiK3JJj`2J-QjHVAbCrKS2Lv1JeJ=^X~K4v zX4WMbKT#otHNse-VjDktz;dRk0pM8q*aRw@b+Tciw=m413VwD4K9tA{Gh2u(Fu~## z-zMaH76f_g2RV$!c=bFEqX69&)TBb<30$O)0Y}@i1j6xLE7D-E2deg56OyLkBP)!mFo4GwQsx-2K+L>d$x?fawG zX&JXe3`@hkDYYEV4sch-eu~~mRm6iwNWHc6Wsv4WJLK_WUY~W zaTufZbrD{j>)~}6JzKBscuWFmht?_8*Lzyi1&@zd{=A;#9?w1_6?)5SIuedr(pogl z9;7A^_?cSQx*_2ws*%-Z55*06n!Lea)pXcf9^mjMht@Tcy`_N;=aJTA@2)`(Q&}(A zYlJ$ChWgq`Ul-uj`6Yb8#dxv2&0*bh&T5?yZ&n?L@i1PULmr`#5xtK}W-WCSP?|Ca zr06Gu7g;NA5#z<(sN8rW9H{|(MAeG~Z-crA{R++a<2 z7pmz{ZmD(csHMvI`5RAhBHaZXBlhC*Cur(CJ@|cM68Z{gb z4TNcc(uy7w3kHy;7XU|}1?+R0_eOA(^CF=CHbx9@{{Tlq|BfUrZcCA@mP!F!#|Wbs zu%u{ugZ0zkivSXy)I%yoZ$=|;=>ra<6JAx>1($ydbP>x7jpbr0++_817)h?nv;!d) zqnT$dOAGMD83>Q%AYBI>y=C|;HFdmkc88}+XR3PBAE+8b$w-U<9Ibqp(Zguvyuec5 z;a1C=QUj)K4EfAppVlHX7p2Aqym~Wg)=fADdKjaEXAK@YMH<+JyPog5)+CwAc;;}b zVF{^=W!@Pur4NA=y@gapXnZtx{ck9RDKilk$8LBvM?6ZJB^}96KaMNALR`G*w(SNf z^p*AqX{;tDo{l9vu{i;y9HUVjTgqfBWlq5q_=x4Hews_0ZD}NIgcL@}XMpq(d9_!*PYx|T%-oDM)w%TGx&xLUNpS|IF9-fpKjW! z>=p26bd=a7%{(i6Q0(Z=)L3}L1L^crLbwG43G%es>eur%aHRjJ*Oa^v7g_z5wHZfylq8HA_=97`43jJ)BwBqUoe?&d^8 z=Vx%YtyKLlL1l_SjP64E6OP9vkxpu{Q9%s$Suca~lmt>1tjrIC!mGup8(Ca1jhx^q z8Kk{{V^=5owC5?-Pa8zB@w_EctKR?Kz%K!=XNX)@l`5!8-Lq0=*yCjH?o3tQ&vohz zxVASZL&^^I7O~V=+*V?yrQuw|KGJSc1LJ`~q%f88H;neCPf&;wek&^_sW<>QR&@+l z)y;T=KBS))NL6jjct4c|?hM!@1!nGGE#KFa;J#MH6RT4BRjJRbQm3qx=Pssjl+2*I z<1r(ozWoSK9zo^UMJ*)8sTo(GgBOAri*J2bux_ZiT5R-G<)CG}rkUqGSXnVfMniIf zKf6MzWV~b^#lZ83NKdGVS0Tn!c!R`&>ih1tO^c1+HS>4|(A;$U%*`%A@ zhsp=%#$94Am2wSo9%9cDo3ELfJCKX*p{RWKXesC{Gt%8>1+`5gpVacXR*alOeQO0AGR|_$~(vTCZRNI-5 z(lLGB0ZsxQ@-H`l-!04Z)M0FCr_xTQ%7}Y_<4~W=GqnR%PB?~>e)0`!j_HhV1|0R1 zeO^ev1Uv+md*6Zj1NmttGK23AJb46F+jmc6w#vE*&3BgAZOxpGo~F_i`;(Je+}1Z# zB`8bxNUJeBV+snAcA1(R&wnBfu{30sl`;zBlns^(U zC`jc4lTj(wJ#j0Hd91weYS$7pu%a2=sZqvr-ydY$cQYqIrQ8Aktu%A?97Wa@!DMZ% z*)Nkg55yR>Sdv%R_0x2W#Qx7v9fp=r&spQkRQ2z|D%cgox(|5&zY|*z)na2Kv7N*Y z6AM!_z|?3?tdC~SG0&2tOm6ez>}ahPn?HaUn=+G&0c*3SfK(nivRzeba8+t;RqDEx zGD4L79z=hd*sH|eCbnHO&$0hdSxQVE^3-tR_tDf;?vd0~_=`QHfvOZ;jw6;q>_=kZ z*(tD>F#@liSH{vT_nl)i0mnuRsY&syHKuR&PO$PmN76E$$@3_vX#YInX}oW1_3KF0 z-vG1MK&%I!Pse%LteBsdtqquS+DsJ~rhhyZCN}#1!W?>m!%1q5^IVKdz%fqUQqqU@ zQj?+LY*384<4Byw;<_wu0yu{8-QVq_&5Yjoj^UZaO2thn=3MRwb38en>*KVQ%7>WF z$5@=_BOay2#sXqRq}*l#7vv_DERGBKq4M}a`A@Rg_r`dQao^UDR6D`U=%bl)Od1t* zn@>rmk=8O|pAZwO5=}!jbGDyIrX_6Z=5oy;@p2I3v<(?UODUfFMmkDPq$>1>mT*j> z%Ej_t6hHlm)+AoQ;)3h64z42~qLs2sD9N*$IbVN~ocL~|6p{E0h;aZk<=qRbhi{XU zCaM&Dbtm=~u{D}GZ%ro8zK@elRZ2Bz`(9JHj!D$-Zkl%D8NhMRDwFrDc-u)V)@H_5 zVm}hQtXbPuQz=v;fB%G0t7#_S*pBW`C3qjN6X~* z$P#~0g49=4LgAe+vzhNrBwLG(?V5Rlr;&5t*Ubk3N9Sq1$vOV=3~7q09{{bHqnY_J zTbHz^x%Uexi+ymn*PEsZw*PVq^CH2^v`Asx-G)s1a?_q--1m-IsqBFew}#3`)3cb_YZw7w*EPBSy~6;e**q1b^cB>DkPPov|jQv0lw5vh#o5OAVq&Rwt4P^;iM zk-P_!Q0_Pwn2CcaCjP+$r0=xYa~j0DDIO&;{(TFigxAS=89TS`uS?ZL zbiP9~=QY-fK1fw|Yg-|jsZ!8N9XOMm`)(eM1{^<3GAE&z!{yGS0 z1zSezBs< zXKdfp$uCWq^!$rOpFd!JE!B=XrnBgc+GZm|%?mSw)ylm}Q8b8kLqT2T{yQ;`|GeEuC$9!DbpE9FtJz5vF ze#qSDr+V}@ANKFjI)19Ra=^nyfi287PH(_~THe$For<>iG*e9F-^zSMWz03JtB~Pl zU9~gBZ00TL=U>$OSu;OK#rHOw`}gp~Pc1q(-b}T{bWBPbJ$_2kGt;KEOGsV37SB_K0Eb#97cCAa zDK9NITiUIYix$7GJUM2opsIt5Y3jKgvz^^KS!r=N>;!6d>j0+3JE+PW6aMFqnz+Jj zRZ|r5Ktk@#w}+|X6=t*nXJHA5I@fF&WF3Tn^Nr8tnmyqVM`138;*&TQ zKdCAK4z*4>R`HIi^-8m)nYWY{3yVjXToz Date: Thu, 3 Sep 2020 10:19:33 -0600 Subject: [PATCH 22/22] Changes to the network spec file. - All the network is included in a network node. - No difference between the primary network and th secondary network, its all just one network - Tests changed to reflect new file spec. --- TapControl/tapcontrol/data/ieee13.json | 2 +- config/reader/Config.py | 8 +- config/reader/tests/ConfigTestCases.py | 11 + .../TestFiles/duplicate_network_id_nodes.json | 2 +- .../TestFiles/duplicate_power_id_nodes.json | 2 +- config/reader/tests/TestFiles/ieee13.json | 275 ++++++++++++++++++ ...lid_network_connections_distance_wifi.json | 2 +- .../not_valid_app_conn_node_one_missing.json | 2 +- .../not_valid_app_conn_node_two_missing.json | 2 +- ...ot_valid_app_conn_wrong_path_type_one.json | 2 +- ...ot_valid_app_conn_wrong_path_type_two.json | 2 +- .../not_valid_network_duplicate_mixed.json | 2 +- .../not_valid_network_duplicate_p2p.json | 2 +- .../not_valid_network_duplicate_wifi.json | 2 +- .../not_valid_network_missing_nic_p2p.json | 2 +- .../not_valid_network_missing_nic_wifi.json | 2 +- .../not_valid_network_missing_node.json | 2 +- ...ot_valid_network_wifi_no_access_point.json | 2 +- ...alid_network_wifi_no_non_access_point.json | 2 +- .../tests/TestFiles/valid_app_conns.json | 2 +- ...alid_network_connections_distance_p2p.json | 2 +- ...lid_network_connections_distance_wifi.json | 2 +- .../valid_network_connections_mixed.json | 2 +- .../valid_network_connections_p2p.json | 2 +- .../valid_network_connections_wifi.json | 2 +- .../reader/tests/TestFiles/valid_nodes.json | 2 +- .../tests/TestFiles/wrong_type_nic.json | 2 +- 27 files changed, 314 insertions(+), 28 deletions(-) create mode 100644 config/reader/tests/TestFiles/ieee13.json diff --git a/TapControl/tapcontrol/data/ieee13.json b/TapControl/tapcontrol/data/ieee13.json index 6a760c8..9a749d2 100644 --- a/TapControl/tapcontrol/data/ieee13.json +++ b/TapControl/tapcontrol/data/ieee13.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "0", diff --git a/config/reader/Config.py b/config/reader/Config.py index 4885214..7114251 100644 --- a/config/reader/Config.py +++ b/config/reader/Config.py @@ -147,18 +147,18 @@ def read_config(self): # Load the config file data = json.load(self.file) # Get the primary network out - primary_network_dict = data["primary_network"] + network_dict = data["network"] # Load the nodes - nodes_dict = primary_network_dict["nodes"] + nodes_dict = network_dict["nodes"] self.__read_nodes_from_network(nodes_dict) # Loads the network connections in the primary network - network_layout_dict = primary_network_dict["network_layout"] + network_layout_dict = network_dict["network_layout"] self.__read_network_connections(network_layout_dict) # Loads the app connections - app_connections_dict = primary_network_dict["app_connections"] + app_connections_dict = network_dict["app_connections"] self.__read_app_connections(app_connections_dict) def __read_nodes_from_network(self, data): diff --git a/config/reader/tests/ConfigTestCases.py b/config/reader/tests/ConfigTestCases.py index f36946c..a8a967b 100644 --- a/config/reader/tests/ConfigTestCases.py +++ b/config/reader/tests/ConfigTestCases.py @@ -25,6 +25,17 @@ class ConfigTestCases(unittest.TestCase): + def test_valid_file(self): + """ + Testing a valid file with ieee13.json. Should produce no errors. + :return: + """ + file = open("TestFiles/ieee13.json") + config = Config(file) + config.read_config() + print(config.get_network_connections_as_json()) + file.close() + def test_valid_nodes(self): """ Passes a file which has valid nodes into Config, no error diff --git a/config/reader/tests/TestFiles/duplicate_network_id_nodes.json b/config/reader/tests/TestFiles/duplicate_network_id_nodes.json index bfff743..67d2755 100644 --- a/config/reader/tests/TestFiles/duplicate_network_id_nodes.json +++ b/config/reader/tests/TestFiles/duplicate_network_id_nodes.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "6", diff --git a/config/reader/tests/TestFiles/duplicate_power_id_nodes.json b/config/reader/tests/TestFiles/duplicate_power_id_nodes.json index 2dbb58c..9ae4a12 100644 --- a/config/reader/tests/TestFiles/duplicate_power_id_nodes.json +++ b/config/reader/tests/TestFiles/duplicate_power_id_nodes.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "0", diff --git a/config/reader/tests/TestFiles/ieee13.json b/config/reader/tests/TestFiles/ieee13.json new file mode 100644 index 0000000..9a749d2 --- /dev/null +++ b/config/reader/tests/TestFiles/ieee13.json @@ -0,0 +1,275 @@ +{ + "network": { + "nodes": [ + { + "id": "0", + "power_network_id": "SourceBus", + "location": { + "x": "200", + "y": "400" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + }, + { + "id": "1", + "power_network_id": "650", + "location": { + "x": "200", + "y": "350" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + }, + { + "id": "2", + "power_network_id": "RG60", + "location": { + "x": "200", + "y": "300" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + }, + { + "id": "3", + "power_network_id": "646", + "location": { + "x": "0", + "y": "250" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + }, + { + "id": "4", + "power_network_id": "645", + "location": { + "x": "100", + "y": "250" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + }, + { + "id": "5", + "power_network_id": "632", + "location": { + "x": "200", + "y": "250" + }, + "nic_card_types": [ + { + "type": "p2p" + }, + { + "type":"wifi", + "access_point": true + }] + }, + { + "id": "6", + "power_network_id": "633", + "location": { + "x": "350", + "y": "250" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + }, + { + "id": "7", + "power_network_id": "634", + "location": { + "x": "400", + "y": "250" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + }, + { + "id": "8", + "power_network_id": "670", + "location": { + "x": "200", + "y": "200" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + }, + { + "id": "9", + "power_network_id": "611", + "location": { + "x": "0", + "y": "100" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + }, + { + "id": "10", + "power_network_id": "684", + "location": { + "x": "100", + "y": "100" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + }, + { + "id": "11", + "power_network_id": "671", + "location": { + "x": "200", + "y": "100" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + }, + { + "id": "12", + "power_network_id": "692", + "location": { + "x": "250", + "y": "100" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + }, + { + "id": "13", + "power_network_id": "675", + "location": { + "x": "400", + "y": "100" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + }, + { + "id": "14", + "power_network_id": "652", + "location": { + "x": "100", + "y": "0" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + }, + { + "id": "15", + "power_network_id": "680", + "location": { + "x": "200", + "y": "0" + }, + "nic_card_types": [ + { + "type": "p2p" + }] + } + ], + "app_connections": [ + { + "receiver": "5", + "sender": "9", + "path_type": "control" + }, + { + "receiver": "1", + "sender": "5", + "path_type": "actuator" + }], + "network_layout": [ + { + "nodes":["0", "1"], + "type": "p2p" + }, + { + "nodes":["1", "2"], + "type": "p2p" + }, + { + "nodes":["6", "7"], + "type": "p2p" + }, + { + "nodes":["10", "11"], + "type": "p2p" + }, + { + "nodes":["4", "5"], + "type": "p2p" + }, + { + "nodes":["5", "6"], + "type": "p2p" + }, + { + "nodes":["8", "11"], + "type": "p2p" + }, + { + "nodes":["11", "12"], + "type": "p2p" + }, + { + "nodes":["12", "13"], + "type": "p2p" + }, + { + "nodes":["9", "10"], + "type": "p2p" + }, + { + "nodes":["10", "14"], + "type": "p2p" + }, + { + "nodes":["11", "15"], + "type": "p2p" + }, + { + "nodes":["2", "5"], + "type": "p2p" + }, + { + "nodes":["3", "4"], + "type": "p2p" + }, + { + "nodes":["5", "8"], + "type": "p2p" + } + ] + } +} diff --git a/config/reader/tests/TestFiles/invalid_network_connections_distance_wifi.json b/config/reader/tests/TestFiles/invalid_network_connections_distance_wifi.json index 2bd303f..ae09911 100644 --- a/config/reader/tests/TestFiles/invalid_network_connections_distance_wifi.json +++ b/config/reader/tests/TestFiles/invalid_network_connections_distance_wifi.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "-1111819", diff --git a/config/reader/tests/TestFiles/not_valid_app_conn_node_one_missing.json b/config/reader/tests/TestFiles/not_valid_app_conn_node_one_missing.json index 8631b33..244098c 100644 --- a/config/reader/tests/TestFiles/not_valid_app_conn_node_one_missing.json +++ b/config/reader/tests/TestFiles/not_valid_app_conn_node_one_missing.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "1111111111", diff --git a/config/reader/tests/TestFiles/not_valid_app_conn_node_two_missing.json b/config/reader/tests/TestFiles/not_valid_app_conn_node_two_missing.json index c1d1ebd..fc4f238 100644 --- a/config/reader/tests/TestFiles/not_valid_app_conn_node_two_missing.json +++ b/config/reader/tests/TestFiles/not_valid_app_conn_node_two_missing.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "1111111", diff --git a/config/reader/tests/TestFiles/not_valid_app_conn_wrong_path_type_one.json b/config/reader/tests/TestFiles/not_valid_app_conn_wrong_path_type_one.json index 28c1196..170a0bd 100644 --- a/config/reader/tests/TestFiles/not_valid_app_conn_wrong_path_type_one.json +++ b/config/reader/tests/TestFiles/not_valid_app_conn_wrong_path_type_one.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "11111112222", diff --git a/config/reader/tests/TestFiles/not_valid_app_conn_wrong_path_type_two.json b/config/reader/tests/TestFiles/not_valid_app_conn_wrong_path_type_two.json index 3ed3549..83359fe 100644 --- a/config/reader/tests/TestFiles/not_valid_app_conn_wrong_path_type_two.json +++ b/config/reader/tests/TestFiles/not_valid_app_conn_wrong_path_type_two.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "111111122222", diff --git a/config/reader/tests/TestFiles/not_valid_network_duplicate_mixed.json b/config/reader/tests/TestFiles/not_valid_network_duplicate_mixed.json index d87e001..0cee1a2 100644 --- a/config/reader/tests/TestFiles/not_valid_network_duplicate_mixed.json +++ b/config/reader/tests/TestFiles/not_valid_network_duplicate_mixed.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "111145", diff --git a/config/reader/tests/TestFiles/not_valid_network_duplicate_p2p.json b/config/reader/tests/TestFiles/not_valid_network_duplicate_p2p.json index 463932d..2d177b8 100644 --- a/config/reader/tests/TestFiles/not_valid_network_duplicate_p2p.json +++ b/config/reader/tests/TestFiles/not_valid_network_duplicate_p2p.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "43", diff --git a/config/reader/tests/TestFiles/not_valid_network_duplicate_wifi.json b/config/reader/tests/TestFiles/not_valid_network_duplicate_wifi.json index ffd5af9..177f67e 100644 --- a/config/reader/tests/TestFiles/not_valid_network_duplicate_wifi.json +++ b/config/reader/tests/TestFiles/not_valid_network_duplicate_wifi.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "45", diff --git a/config/reader/tests/TestFiles/not_valid_network_missing_nic_p2p.json b/config/reader/tests/TestFiles/not_valid_network_missing_nic_p2p.json index c76b49c..8186a6e 100644 --- a/config/reader/tests/TestFiles/not_valid_network_missing_nic_p2p.json +++ b/config/reader/tests/TestFiles/not_valid_network_missing_nic_p2p.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "43123213", diff --git a/config/reader/tests/TestFiles/not_valid_network_missing_nic_wifi.json b/config/reader/tests/TestFiles/not_valid_network_missing_nic_wifi.json index ae903b3..c3a83d7 100644 --- a/config/reader/tests/TestFiles/not_valid_network_missing_nic_wifi.json +++ b/config/reader/tests/TestFiles/not_valid_network_missing_nic_wifi.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "434321321", diff --git a/config/reader/tests/TestFiles/not_valid_network_missing_node.json b/config/reader/tests/TestFiles/not_valid_network_missing_node.json index 10b4aca..c0b3ae8 100644 --- a/config/reader/tests/TestFiles/not_valid_network_missing_node.json +++ b/config/reader/tests/TestFiles/not_valid_network_missing_node.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "430000", diff --git a/config/reader/tests/TestFiles/not_valid_network_wifi_no_access_point.json b/config/reader/tests/TestFiles/not_valid_network_wifi_no_access_point.json index 003c324..4e9284b 100644 --- a/config/reader/tests/TestFiles/not_valid_network_wifi_no_access_point.json +++ b/config/reader/tests/TestFiles/not_valid_network_wifi_no_access_point.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "21111", diff --git a/config/reader/tests/TestFiles/not_valid_network_wifi_no_non_access_point.json b/config/reader/tests/TestFiles/not_valid_network_wifi_no_non_access_point.json index 290fb32..1206093 100644 --- a/config/reader/tests/TestFiles/not_valid_network_wifi_no_non_access_point.json +++ b/config/reader/tests/TestFiles/not_valid_network_wifi_no_non_access_point.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "211143211", diff --git a/config/reader/tests/TestFiles/valid_app_conns.json b/config/reader/tests/TestFiles/valid_app_conns.json index 9ceb5c7..498f7eb 100644 --- a/config/reader/tests/TestFiles/valid_app_conns.json +++ b/config/reader/tests/TestFiles/valid_app_conns.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "-111", diff --git a/config/reader/tests/TestFiles/valid_network_connections_distance_p2p.json b/config/reader/tests/TestFiles/valid_network_connections_distance_p2p.json index 3840ba5..e9c196d 100644 --- a/config/reader/tests/TestFiles/valid_network_connections_distance_p2p.json +++ b/config/reader/tests/TestFiles/valid_network_connections_distance_p2p.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "-11111", diff --git a/config/reader/tests/TestFiles/valid_network_connections_distance_wifi.json b/config/reader/tests/TestFiles/valid_network_connections_distance_wifi.json index 9df09a2..e837892 100644 --- a/config/reader/tests/TestFiles/valid_network_connections_distance_wifi.json +++ b/config/reader/tests/TestFiles/valid_network_connections_distance_wifi.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "-111181", diff --git a/config/reader/tests/TestFiles/valid_network_connections_mixed.json b/config/reader/tests/TestFiles/valid_network_connections_mixed.json index d374148..b167829 100644 --- a/config/reader/tests/TestFiles/valid_network_connections_mixed.json +++ b/config/reader/tests/TestFiles/valid_network_connections_mixed.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "1111", diff --git a/config/reader/tests/TestFiles/valid_network_connections_p2p.json b/config/reader/tests/TestFiles/valid_network_connections_p2p.json index de6d95f..72df21c 100644 --- a/config/reader/tests/TestFiles/valid_network_connections_p2p.json +++ b/config/reader/tests/TestFiles/valid_network_connections_p2p.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "11111", diff --git a/config/reader/tests/TestFiles/valid_network_connections_wifi.json b/config/reader/tests/TestFiles/valid_network_connections_wifi.json index ddc51bb..e10f8de 100644 --- a/config/reader/tests/TestFiles/valid_network_connections_wifi.json +++ b/config/reader/tests/TestFiles/valid_network_connections_wifi.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "21", diff --git a/config/reader/tests/TestFiles/valid_nodes.json b/config/reader/tests/TestFiles/valid_nodes.json index cc457c2..cdf81a4 100644 --- a/config/reader/tests/TestFiles/valid_nodes.json +++ b/config/reader/tests/TestFiles/valid_nodes.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "3", diff --git a/config/reader/tests/TestFiles/wrong_type_nic.json b/config/reader/tests/TestFiles/wrong_type_nic.json index e6bd70d..41d3dc9 100644 --- a/config/reader/tests/TestFiles/wrong_type_nic.json +++ b/config/reader/tests/TestFiles/wrong_type_nic.json @@ -1,5 +1,5 @@ { - "primary_network": { + "network": { "nodes": [ { "id": "8",