Using WPF to Interact with Indicators in MultiCharts .Net (Trading Program) - c#

I am trying to create a WPF form using Visual Studio C# that will interact with indicators I create for my trading charts in MultiCharts .Net
I've added a WPF Project to the solution and added the namespace for the indicators. However, I can not figure out how I can manipulate inputs for the indicator object. Any help from someone who works with this program would be much appreciated.

You have to create a local network connection to make this work--I used sockets, but anything in a similar way will support the same goal:
Make a new MC indicator like so:
public class tests_OwnApp : IndicatorObject {
public tests_OwnApp(object _ctx):base(_ctx)
{
PortNumber = 5000;
}
[Input]
public int PortNumber { get; set; }
public static string Symbol;
const string ServerIP = "127.0.0.1";
IPAddress localAdd;
TcpListener listener;
TcpClient client;
NetworkStream nwStrm;
private IPlotObject plot1;
protected override void Create() {
// create variable objects, function objects, plot objects etc.
plot1 = AddPlot(new PlotAttributes("", EPlotShapes.Line, Color.Red));
localAdd = IPAddress.Parse(ServerIP);
client = null;
}
protected override void StartCalc() {
// assign inputs
// establish connection
if (listener == null)
{
listener = new TcpListener(localAdd, PortNumber);
}
listener.Stop();
Thread.Sleep(100);
listener.Start();
}
protected override void CalcBar()
{
// indicator logic
if (Bars.LastBarTime <= Bars.Time[0] + new TimeSpan(2,0,0))
{
Symbol = Bars.Info.Name;
if (client == null || !client.Connected)
client = listener.AcceptTcpClient();
// create network stream
nwStrm = client.GetStream();
// send symbol to app:
Output.WriteLine("sending " + Symbol + " to application");
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(Symbol);
string closingPrice = Convert.ToString(Bars.Close[0]);
string totalMsg = "Sym," + Symbol +
"\nClose[0]," + closingPrice + "\nClose[1]," + Bars.Close[1].ToString();
byte[] bytes2 = ASCIIEncoding.ASCII.GetBytes(totalMsg);
nwStrm.Write(bytes2, 0, bytes2.Length);
}
}
}
In your app (Console App example, extends to WPF):
static void Main(string[] args)
{
const int PortNum = 5000;
const string ServerIP = "127.0.0.1";
DateTime startTime = DateTime.Now;
TcpClient client = new TcpClient(ServerIP, PortNum);
NetworkStream nwStream = client.GetStream();
while (true)
{
if (client.ReceiveBufferSize != 0)
{
nwStream = client.GetStream();
byte[] bytesToRead = new byte[client.ReceiveBufferSize];
int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
string msg = Encoding.ASCII.GetString(bytesToRead, 0, bytesRead);
Console.WriteLine("received: " + msg);
if (DateTime.Now - new TimeSpan(0, 0, 30) > startTime)
{
break;
}
Thread.Sleep(100);
Console.Write("-ping-");
}
}
Console.ReadLine();
}
Run them both together and you'll find they connect and the info is received.
I used this example to get started, in case my example is not sufficient.
Be sure to include all the necessary namespaces:
using System.Net;
using System.Net.Sockets;

See the documentation I believe chapter three shows you how to work with indicators

Related

How to keep telnet port 23 open to keep reading data coming in, in C# windows form

I finally got the program to work as I wanted is reading the data from the telnet port for every scan it triggers, but now the only problem I am getting is that is reading the data if I display it in the console but I need it display into my main display which will be a text box multiline, can you see why I am getting this
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace BarcodeReceivingApp
{
public partial class BarcodeReceivingForm : Form
{
public BarcodeReceivingForm()
{
InitializeComponent();
}
private Thread _readWriteThread;
private TcpClient _client;
private NetworkStream _networkStream;
private void btn_ConnectToTelnetPort_Click(object sender, EventArgs e)
{
// connection tcp/ip
const string hostname = "myipaddress";
const int port = 23;
ServerSocket(hostname, port);
//Connect();
}
public void ServerSocket(string ip, int port)
{
try
{
_client = new TcpClient(ip, port);
lbl_ConnectionMessage.Text = #"Connected to server.";
}
catch (SocketException)
{
MessageBox.Show(#"Failed to connect to server");
return;
}
//Assign networkstream
_networkStream = _client.GetStream();
//start socket read/write thread
_readWriteThread = new Thread(ReadWrite);
_readWriteThread.Start();
}
private void ReadWrite()
{
var received = "";
//Read first thing givent o us
received = Read();
//Console.WriteLine(received);
txt_BarcodeDisplay.Text = received + Environment.NewLine;
//txt_BarcodeDisplay.Text = recieved.ToString();
//Set up connection loop
while (true)
{
var command = btn_StopConnection.Text;
if (command == "STOP1")
break;
//write(command);
received = Read();
//Console.WriteLine(received);
txt_BarcodeDisplay.Text += received + Environment.NewLine;
}
// possible method to end the port connection
}
public string Read()
{
byte[] data = new byte[1024];
var received = "";
var size = _networkStream.Read(data, 0, data.Length);
received = Encoding.ASCII.GetString(data, 0, size);
return received;
}
private void btn_StopConnection_Click(object sender, EventArgs e)
{
_networkStream.Close();
_client.Close();
}
}
}
Here is I am adding the error and is coming from the ReadWrite method
enter image description here
So you'll have to have a loop somewhere to have your program keep checking the Stream. Usually the easiest was is with a Boolean indicator, so something list this:
Boolean openConnection = false;
This would need to be class level. Then inside your connect method, you loop and listen. Something like this.
NetworkStream ns = server.GetStream();
openConnection = True;
Task.Factory.StartNew(() =>
{
while (openConnection)
{
ns.Read(data, 0, data.Length);
var stringData = Encoding.ASCII.GetString(data, 0, 1024);
dataToAdd.Add(stringData);
foreach (var list in dataToAdd)
{
txt_BarcodeDisplay.Text += list + Environment.NewLine;
}
Thread.Sleep(2000);
}
}
);
So this is a lot to unpack, but basically you're saying, go read what comes in from the network, do it until the openConnection variable is set to false. Oh and since we don't want to peg the processor at 100%, Sleep the thread so we only check every 2 seconds.
This is a rough start, but I hope it will give you an idea of the direction you need to take this.

Very basic web server in C#

I'm wanting to run a little socket server in C# to be accessed by a browser. I have a socket listener up and running on a specific port, and am trying to access it via the browser:
class WebSocketServer
{
private static string output = string.Empty;
public void CreateListener()
{
TcpListener tcpListener = null;
var ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
try
{
tcpListener = new TcpListener(ipAddress, 1313);
tcpListener.Start();
output = "Waiting for a connection";
}
catch (Exception e)
{
throw;
}
var socketHelper = new SocketHelper();
while (true)
{
Thread.Sleep(10);
TcpClient tcpClient = tcpListener.AcceptTcpClient();
byte[] bytes = new byte[256];
var stream = tcpClient.GetStream();
stream.Read(bytes, 0, bytes.Length);
socketHelper.ProcessMessage(tcpClient, stream, bytes);
}
}
}
class SocketHelper
{
private static int counter = 0;
public void ProcessMessage(TcpClient tcpClient, NetworkStream stream, byte[] bytesReceived)
{
// handle message received and send response to client
var msg = Encoding.ASCII.GetString(bytesReceived);
string response = string.Empty;
if (msg.Substring(0, 10) == "GET / HTTP")
{
response = "";// html page
}
byte[] bytesToSend = Encoding.ASCII.GetBytes(response);
stream.Write(bytesToSend, 0, bytesToSend.Length);
}
The browser appears to connect to it, but it never seems to display the html - what's wrong? I'm eventually wanting to be able to serve up JSON data via a REST interface. In addition, is there a much easier solution to (I assume) this common problem.

C# TCP Chat Application Threading

I am in desperate need of help. I have essentially created a program that (will use) encryption to send messages back and forth. The encryption part is working fine, however I am fairly new to Threads and I can not for the life of me get my Client/Server pieces of the application to line up. The chat program is direct IP connection using TCP, so each host is a client and a server. The issue I appear to be having, when I debug, is that the server thread is either not ready when the Client tries to connect to it, or if it is ready it will not relinquish the Thread so the Client can connect! I have been working on this for hours and it is very frustrating.. I hope someone can help! I've included my code below.
This is my code snippet from my MainForm, which constructs the Client and Server aspects:
private void InitializeComponent() {
server = new ServerSide("127.0.0.1",7865);
servThread = new Thread(new ThreadStart(server.begin));
client = new ClientSide("127.0.0.1",7865);
clientThread = new Thread(new ThreadStart(client.begin));
servThread.Start();
clientThread.Start();
//servThread.Join();
//clientThread.Join();
}
This is my ServerSide code:
public class ServerSide
{
String IpString;
int tcpPort;
bool goodToGo = false;
System.Net.IPAddress ipAddress = null;
public ServerSide(String ip, int tcpPort)
{
IpString = ip;
bool isValidIp = System.Net.IPAddress.TryParse(IpString, out ipAddress);
if (isValidIp == true) // check if the IP is valid, set the bool to true if so
{
goodToGo = true;
}
else
{
goodToGo = false;
}
}
public void begin()
{
try
{
IPAddress ipAd = IPAddress.Parse(IpString);
/* Initializes the Listener */
TcpListener myList = new TcpListener(ipAd, tcpPort);
Socket s = null;
/* Start Listening at the specified port */
while (true)
{
myList.Start();
if (myList.Pending())
{
s = myList.AcceptSocket();
break;
}
}
String toReceive = "";
while (true)
{
byte[] b = new byte[4096];
int k = s.Receive(b);
for (int i = 0; i < k; i++)
toReceive += Convert.ToString((Convert.ToChar(b[i])));
// ASCIIEncoding asen = new ASCIIEncoding();
var form = MainForm.ActiveForm as MainForm;
if (form != null)
{
form.messageReceived(toReceive);
}
toReceive = "";
}
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
}
}
}
}
ClientSide code:
public class ClientSide
{
private String IpString;
private int tcpPort;
private TcpClient tcpInt;
private static Stream stm;
private System.Net.IPAddress ipAddress = null;
private bool goodToGo = false;
public ClientSide(String ip, int tcpPort)
{
IpString = ip;
this.tcpPort = tcpPort;
bool isValidIp = System.Net.IPAddress.TryParse(IpString, out ipAddress);
if (isValidIp == true)
{
goodToGo = true;
}
else
{
goodToGo = false;
}
}
public void begin()
{
try
{
tcpInt = new TcpClient();
// Console.WriteLine("Connecting.....");
tcpInt.Connect(IpString, tcpPort);
// use the ipaddress as in the server program
// Console.WriteLine("Connected");
// String str = Console.ReadLine();
stm = tcpInt.GetStream();
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
}
}
public void sendMessage(String str)
{
// stm = tcpInt.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(str);
stm.Write(ba, 0, ba.Length);
/** byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
for (int i = 0; i < k; i++)
Console.Write(Convert.ToChar(bb[i]));*/
}
}
}
Once again.. what typically happens is my Client receives an error that the host actively refused the connection.. but I do not know how to time them. I am looking for how to have my server listening for TCP Connections, but still manage to go to my other thread to create the TCP Connecion to send the server (I am testing this on localhost currently).
Thanks.
In the constructor of the ServerSide class, you forgot to initialize the tcpPort member. Because you forgot, the server will try to listen to port 0 and the client will try to connect to port 7865, and it will fail.
Try adding this code to the constructor in the ServerSide class.
this.tcpPort = tcpPort;
As for the threads, you might have a problem if the client thread tries to connect before the server thread has started listening. You can use a loop to try to connect a number of times (let's say 10), with a timeout (let's say 1 second) if you don't succeed. This way, you will retry 10 times and give up after that.

send complex object using socket in C# but also simple text string

my goal is to send simple text data and also complex data to client application using socket..this is some of my code
private void button1_Click(object sender, EventArgs e)
{
byte[] data;
data = Encoding.ASCII.GetBytes("Welcome!!!");
ns.Write(data, 0, data.Length);
ns.Flush();
List<Person> list = new List<Person>();
for (int a = 0; a < 5; a++)
{
Person person = new Person();
person.Name = textBox1.Text;
person.Age = int.Parse(textBox2.Text);
list.Add(person);
}
BinaryFormatter formatter = new BinaryFormatter();
for (int a = 0; a < 5; a++)
{
formatter.Serialize(ns, list[a]);
}
ns.Flush();
}
and at the client i write this code to add all data to listview
private void AddToListView()
{
while (true && ns.DataAvailable)
{
byte[] data = new byte[1024];
int recv;
recv = ns.Read(data, 0, data.Length);
textFromServer = Encoding.ASCII.GetString(data, 0, recv);
ns.Flush();
listView1.Items.Add(textFromServer);
temp = formatter.Deserialize(ns) as Person;
ns.Flush();
listView1.Items.Add(temp.Name);
listView1.Items.Add(temp.Age);
}
}
but when i debug the application,,nothing happens...if i delete the networkstream read() process,,the application run nicely..the problem is,i not only need to send the user object,,but also simple text to client..can someone help me please?
is it possible using networkstream.read() and binaryformatter.deserialize() at the same time??or,we have to choose one of it?
i mean when just to send/receive simple text,,we use networkstream.read()/write(),,and for complex object we use serialize/deserialize..is it possible??
The problem with what you are doing is that the server and client need to have an agreed upon protocol by which to send and receive data. For instance your Client code will read everything that is available in the first ns.Read call you make. There is nothing that signals the end of one type of data and the beginning of the next, and thus you don't have an agreed upon method by which you are sending/reading data.
Easiest might be for you to encapsulate the data into another object that can contain both strings and objects.
[Serializable]
public class EncapsulatedData{
public EncapsulatedData(){}
public string Message{ get; set; }
public ISerializable Object{ get; set; }
}
And you will set Object to be a ISerializable type of yours, such as Person. Then you should be able to deserialize on the client and check Message or Object.
There are cleaner ways to do this, but the above trick should work for you.
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace ClientServer
{
class ClientServerProgram
{
public static void SendHeader(string sMIMEHeader, int iTotBytes, string sStatusCode, ref Socket mySocket)
{
String sBuffer = "";
// if Mime type is not provided set default to text/html
if (sMIMEHeader.Length == 0)
{
sMIMEHeader = "text/html"; // Default Mime Type is text/html
}
sBuffer = sBuffer + "HTTP/1.1" + sStatusCode + "\r\n";
sBuffer = sBuffer + "Server: cx1193719-b\r\n";
sBuffer = sBuffer + "Content-Type: " + sMIMEHeader + "\r\n";
sBuffer = sBuffer + "Accept-Ranges: bytes\r\n";
sBuffer = sBuffer + "Content-Length: " + iTotBytes + "\r\n\r\n";
Byte[] bSendData = Encoding.ASCII.GetBytes(sBuffer);
mySocket.Send(Encoding.ASCII.GetBytes(sBuffer),Encoding.ASCII.GetBytes(sBuffer).Length, 0);
Console.WriteLine("Total Bytes : " + iTotBytes.ToString());
}
public static void ReceiveCallback(IAsyncResult AsyncCall)
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
string messageString = "I am a little busy, come back later!";
Byte[] message = encoding.GetBytes(messageString);
Socket listener = (Socket)AsyncCall.AsyncState;
Socket client = listener.EndAccept(AsyncCall);
Console.WriteLine("Received Connection from {0}", client.RemoteEndPoint);
SendHeader("text/html", message.Length, "202 OK", ref client);
client.Send(message);
Console.WriteLine("Ending the connection");
client.Close();
listener.BeginAccept(new AsyncCallback(ReceiveCallback), listener);
}
public static void Main()
{
IPAddress localAddress = IPAddress.Parse("192.0.127.1");
Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipEndpoint = new IPEndPoint(localAddress, 8080);
listenSocket.Bind(ipEndpoint);
listenSocket.Listen(1);
listenSocket.BeginAccept(new AsyncCallback(ReceiveCallback), listenSocket);
while (true)
{
Console.WriteLine("Waiting....");
Thread.Sleep(1000);
}
}
}

C# Socket Server - Issue with Concurrent Connections

hey all,
I have made a socket server in C# for a flash game that I am developing, I got the code from somewhere and I am a beginner in c# and .net development . It works fine in practice when connections are made and the server functions correctly. Get 2 concurrent connections at the same time and we have a problem.
here is the basic aspects of the socket server below: (alot taken out for obvious reasons)
how can I alter this so that it can handle concurrent connections? Should I be threading each response?
Thanks
class TcpSock
{
int tcpIndx = 0;
int tcpByte = 0;
byte[] tcpRecv = new byte[1024];
////////////////////////////////////////
public Socket tcpSock;
////////////////////////////////////////
public int Recv(ref string tcpRead)
{
tcpByte = tcpSock.Available;
if (tcpByte > tcpRecv.Length - tcpIndx)
tcpByte = tcpRecv.Length - tcpIndx;
tcpByte = tcpSock.Receive(tcpRecv, tcpIndx, tcpByte,
SocketFlags.Partial);
tcpRead = Encoding.ASCII.GetString
(tcpRecv, tcpIndx, tcpByte);
tcpIndx += tcpByte;
return tcpRead.Length;
}
public int RecvLn(ref string tcpRead)
{
tcpRead = Encoding.ASCII.GetString
(tcpRecv, 0, tcpIndx);
tcpIndx = 0;
return tcpRead.Length;
}
public int Send(string tcpWrite)
{
return tcpSock.Send(Encoding.ASCII.GetBytes(tcpWrite));
}
public int SendLn(string tcpWrite)
{
return tcpSock.Send(Encoding.ASCII.GetBytes(tcpWrite + "\r\n"));
}
}
[STAThread]
static void Main()
{
Thread Server1 = new Thread(RunServer);
Server1.Start();
}
static void RunServer()
{
///class IPHostEntry : Stores information about the Host and is required
///for IPEndPoint.
///class IPEndPoint : Stores information about the Host IP Address and
///the Port number.
///class TcpSock : Invokes the constructor and creates an instance.
///class ArrayList : Stores a dynamic array of Client TcpSock objects.
IPHostEntry Iphe = Dns.Resolve(Dns.GetHostName());
IPEndPoint Ipep = new IPEndPoint(Iphe.AddressList[0], 4444);
Socket Server = new Socket(Ipep.Address.AddressFamily,SocketType.Stream, ProtocolType.Tcp);
///Initialize
///Capacity : Maximux number of clients able to connect.
///Blocking : Determines if the Server TcpSock will stop code execution
///to receive data from the Client TcpSock.
///Bind : Binds the Server TcpSock to the Host IP Address and the Port Number.
///Listen : Begin listening to the Port; it is now ready to accept connections.
ArrayList Client = new ArrayList();
string[,] Users = new string[1000,9];
string rln = null;
string[] Data;
Client.Capacity = 1000;
Server.Blocking = false;
Server.Bind(Ipep);
Server.Listen(32);
Console.WriteLine("Server 1 {0}: listening to port {1}", Dns.GetHostName(), Ipep.Port);
////////////////////////////////////////////////////////////////////////////////////////////
///Main loop
///1. Poll the Server TcpSock; if true then accept the new connection.
///2. Poll the Client TcpSock; if true then receive data from Clients.
while (true)
{
//Accept - new connection
#region new connection
if (Server.Poll(0, SelectMode.SelectRead))
{
int i = Client.Add(new TcpSock());
((TcpSock)Client[i]).tcpSock = Server.Accept();
Console.WriteLine("Client " + i + " connected.");
Users[i, 0] = i.ToString();
}
#endregion
for (int i = 0; i < Client.Count; i++)
{
//check for incoming data
if (((TcpSock)Client[i]).tcpSock.Poll(0, SelectMode.SelectRead))
{
//receive incoming data
if (((TcpSock)Client[i]).Recv(ref rln) > 0)
{
Console.WriteLine(rln.ToString());
Data = rln.Split('|');
// 1) initial connection
#region InitialConnection
if (Data[0] == "0000")
{
}
}
}
}
}
}
You will need to not use synchronous functions but asynchrounus functions like Socket.BeginReceive
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
public static partial class TcpServer
{
public static void Main()
{
// Setup listener on "localhost" port 12000
IPAddress ipAddr = Dns.GetHostEntry("localhost").AddressList[0];
TcpListener server = new TcpListener(ipAddr, 12000);
server.Start(); // Network driver can now allow incoming requests
// Accept up to 1 client per CPU simultaneously
Int32 numConcurrentClients = Environment.ProcessorCount;
for (Int32 n = 0; n
private static Byte[] ProcessData(Byte[] inputData)
{
String inputString = Encoding.UTF8.GetString(inputData, 1, inputData[0]);
String outputString = inputString.ToUpperInvariant();
Console.WriteLine("Input={0}", inputString);
Console.WriteLine(" Output={0}", outputString);
Console.WriteLine();
Byte[] outputStringBytes = Encoding.UTF8.GetBytes(outputString);
Byte[] outputData = new Byte[1 + outputStringBytes.Length];
outputData[0] = (Byte)outputStringBytes.Length;
Array.Copy(outputStringBytes, 0, outputData, 1, outputStringBytes.Length);
return outputData;
}
}
public static partial class TcpServer
{
private sealed class ClientConnectionApm
{
private TcpListener m_server;
private TcpClient m_client;
private Stream m_stream;
private Byte[] m_inputData = new Byte[1];
private Byte m_bytesReadSoFar = 0;
public ClientConnectionApm(TcpListener server)
{
m_server = server;
m_server.BeginAcceptTcpClient(AcceptCompleted, null);
}
private void AcceptCompleted(IAsyncResult ar)
{
// Connect to this client
m_client = m_server.EndAcceptTcpClient(ar);
// Accept another client
new ClientConnectionApm(m_server);
// Start processing this client
m_stream = m_client.GetStream();
// Read 1 byte from client which contains length of additional data
m_stream.BeginRead(m_inputData, 0, 1, ReadLengthCompleted, null);
}
private void ReadLengthCompleted(IAsyncResult result)
{
// If client closed connection; abandon this client request
if (m_stream.EndRead(result) == 0) { m_client.Close(); return; }
// Start to read 'length' bytes of data from client
Int32 dataLength = m_inputData[0];
Array.Resize(ref m_inputData, 1 + dataLength);
m_stream.BeginRead(m_inputData, 1, dataLength, ReadDataCompleted, null);
}
private void ReadDataCompleted(IAsyncResult ar)
{
// Get number of bytes read from client
Int32 numBytesReadThisTime = m_stream.EndRead(ar);
// If client closed connection; abandon this client request
if (numBytesReadThisTime == 0) { m_client.Close(); return; }
// Continue to read bytes from client until all bytes are in
m_bytesReadSoFar += (Byte)numBytesReadThisTime;
if (m_bytesReadSoFar
private void WriteDataCompleted(IAsyncResult ar)
{
// After result is written to client, close the connection
m_stream.EndWrite(ar);
m_client.Close();
}
}
}
First of all: Stop using non-blocking sockets. In .NET you should either stick to the synchronous methods Receive/Send or asynchronous methods BeginReceive/BeginSend.
You should only stick with sync methods if you will have only a handful of clients. Then launch each new client in a new thread. This is the easiest option to get everthing running.
Simply do like this:
public void AcceptClients()
{
TcpListener listener = new TcpListener(IPAddress.Any, 5566);
listener.Start();
while (_serverRunning)
{
var socket = listener.AcceptSocket();
new Thread(ClientFunc).Start(socket);
}
}
public void ClientFun(object state)
{
var clientSocket = (Socket)state;
var buffer = new byte[65535];
while (_serverRunning)
{
//blocking read.
clientSocket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
//check packet.
// handle packet
// send respons.
clientSocket.Send(alalalal);
}
}
You should refactor the methods so that they follow SRP. The code is just a small guide to get you going.

Categories

Resources