Background 

A couple of months ago, my company has a competition on html5. It reminds me an OPT subject when I was still a student. I brought this idea into the competition to maximized applying html5 features in. There are two most important features I put in the competition. A) Canvas, B) Websocket. There are three functions implemented in the application: P2P communication on webpage, Animation on canvas, Subscription on webpage

Introduction

  • I wrote a .NET windows form application as websocket server. In the windows application, I implemented an OPT logic. And open all key events to external programming through socket. Actually, any socket connections are able to get the data from the server. 

  • I will not explain too much detail on OPT. Basically, the question is to produce P.

To produce P, two components need to be produced first: P1 and P2. We can make money from selling P as well as P1, P2. The price of P > the price of P1+P2.

There are 3 machines: one Red machine, one Green machine, one Yellow machine to produce P1, P2 and P.

To produce P1, the red machine needs to warm up for A minutes (I forgot the number) and produce one P1 need ** dollars.

To produce P2, the green machine needs to warm up for B minutes, then work on P2 for C minutes. This is the first step. The second step is to warm up red machine for D minutes to work on P2 for E minutes. At this time, the red machine will stop producing P1(we have only one red machine) and then green machine to continue working on P2 for the third step to work out P2.

To produce P, the yellow machine needs to warm up for F minutes. With one P1 and one P2, the yellow machine will produce one P for G minutes.

All the manufactures need money.

Pay salary every week

The question is: how to manage the production to get a maximum revenue.

  • I put an arithmetic I think is the best in the window application. After you push the GO button, the application will run the arithmetic to get the maximum revenue. 
Picture_3.png
  • I reproduced all effects on the windows form into a web page.
Picture_4.png

Using the Code

WebSocket

  • I referred http://www.codeproject.com/KB/webservices/c_sharp_web_socket_server.aspx?bcsi_scan_84C04EB1A8996739=IUdio+8K+Vb+tVCNrQ5lbwYAAABJQgES&bcsi_scan_filename=c_sharp_web_socket_server.aspx to write websocket server The most important part for websocket connection is the handshake information. When chrome try to connect one websocket server, it will send out a handshake information
GET /chat HTTP/1.1 
Upgrade: WebSocket 
Connection: Upgrade 
Host: www.zendstudio.net:9108 
Origin: http://www.zendstudio.net 
Cookie: somenterCookie
when the server get the information, reply
HTTP/1.1 101 Web Socket Protocol Handshake 
Upgrade: WebSocket 
Connection: Upgrade 
WebSocket-Origin: localhost
WebSocket-Location: ws://localhost/chat

to set up the connection

  • All the key data produced during P, P1 and P3 production will be subscribed through websocket. There are 3 structures were defined to contain those information:
//JSonObject has an extension method to convert the object to JSON object
public class MileStoneMessage :JSonObject
    {
        #region Properties N:Total number; R: Remain number; S:Sales Number; 
        SR: Sales Revenue; M:Material
        public int P_N { get; set; }
        public int P_R { get; set; }
        public int P_S { get; set; }
        public decimal P_SR { get; set; }
        public int P2_N { get; set; }
        public int P2_R { get; set; }
        public int P2_S { get; set; }
        public int P2_U { get; set; }
        public decimal P2_SR { get; set; }
        public int P1_N { get; set; }
        public int P1_R { get; set; }
        public int P1_S { get; set; }
        public int P1_U { get; set; }
        public decimal P1_SR { get; set; }
        public decimal Salary { get; set; }
        public decimal MCost { get; set; }
        public decimal M_R { get; set; }
        public string T_P { get; set; }
        #endregion
    }
public class ClientInstruction : JSonObject
    {
     
        public InstructionType Type { get; set; }
        public int Number { get; set; }
        public string Sender { get; set; }
        public string To { get; set; }
        public string Notice{ get; set; }
    }
  • Websocket server also accept below instructions to control the windows form which means, we can control window form from web page.
[DataContract]
    public enum InstructionType
    {
        [EnumMember]
        Auto=0,
        [EnumMember]
        Manual=1,
        [EnumMember]
        Start=2,
        [EnumMember]
        Pause=3,
        [EnumMember]
        Stop=4,
        [EnumMember]
        Timer=5,
        [EnumMember]
        InputP1=6,
        [EnumMember]
        InputP2=7,
        [EnumMember]
        Private = 8,//private message
        [EnumMember]
        Register = 9//new user
    }
  • Server send out message
public void SendToAll(string message)
        {
            foreach (var c in Connections)
            {
                try
                {
                    if (!c.Send(message)) DisposedConnections.Add(c);
                }
                catch
                {
                    DisposedConnections.Add(c);
                }
            }
            foreach (var c in DisposedConnections)
            {
                Connections.Remove(c);
            }
            DisposedConnections.Clear();
        }
  • Javascript connect websocket server
ws = new WebSocket('ws://' + document.getElementById("server").value + 
    ':8181/TWCompetition', 'ClientInstruction');
        ws.onopen = function () {
            status = 1;
            for (var i = 0; i < onOpenEventListeners.length; i++)
                onOpenEventListeners[i]();
        }
        ws. önclose = function () {
            status = 0;
            for (var i = 0; i < onCloseEventListeners.length; i++)
                onCloseEventListeners[i]();
        }
  • Javascipt receives messages from websocket
        ws.onmessage = function (evt) {
            var message = eval('(' + evt.data + ')');
            switch (message.Key) {
                case "InitData":
                    if (message.Trace.length > 0) RenderMoneyInitTrace(
                        "MoneyDashboard", message.Trace, "MoneyIcon");
                    break;
                case "Users":
                    OnlineUsers = message;
                    DisplayUsers();

                    break;
                case "Private":
                    var sender = message.Sender;
                    var conversationMessage = message.Message;
                    var name;
                    
                    if(conversationMessage=="black you"){
                        if(blackyouObj!=null) {
                            blackyouObj.OpenBlack();
                            ClosePrivateWindow("PW"+sender);
                            return;
                        }
                    }
                    for (i = 0; i < OnlineUsers.Keys.length; i++) {
                        if (OnlineUsers.Keys[i] == sender) {
                            name = OnlineUsers.Names[i];
                        }
                    }
                    PrivateConversation(sender, name, conversationMessage)
                    break;
                case "Register":
                    Token = message.Token;
                    SendName(document.getElementById('name').value);
                    break;
                case "OneSecond":
                    for (var i = 0; i < onSecondEventListeners.length; i++)
                        onSecondEventListeners[i](message);
                    break;
                default:
                    for (var j = 0; j < onMilestoneEventListeners.length; j++)
                        onMilestoneEventListeners[j](message);
                    break;
            }
        }
    }
  • Javascipt send back instructions
var SendInstruction = function (type, number) {
    var json = JSON.stringify({ Type: type, Number: number });
    ws.Send(json);
}

Canvas

To some degree, the syntax in javascript to draw shapes on canvas is kinda of exactly like GDI+ syntax. Javascript draw line:

ctx.beginPath();
    ctx.moveTo(14, 10);
    ctx.lineTo(23, 15);
    ctx.lineTo(14, 20);
    ctx.closePath();

Javascript draw gradient:

grd = ctx.createLinearGradient(0, canvas.height-mywidth, 0, canvas.height);
    grd.addColorStop(0, "gray");
    grd.addColorStop(0.5, "white");
    grd.addColorStop(1, "gray");

How to Demonstrate

  • under WindowsOpt folder, double click opt.exe
  • have a look at the right upper corner of the windows form,select a workable IP to build the client connection. ip.png
  • Click GO button on Game Control panel, the windows form begins to run the animation.
  • gamecontr</p>
<p>•Under WebOPT folder, open WebOPT.html with the latest chrome</p>
<p>•Input the ip you got from the windows form into Server textbox on right upper corner and click Login (you can also input your personal name instead of keeping Will). If the connection is ok, you will see “websocket connection open” in the right Log panel. If there is “websocket connection close” means something I don’t know wrong.<imghttp://www.codeproject.com//KB/applications/ src=

  • After you set up the websocket, you will see the exact same animation like windows form on your webpage and you can also control the game.
  • pa.png status.png

  • You can also see a thoughtworker is running on the screen tw.png
  • P2P communication, a little bit like google talk
  • Login the WebOPT.html in a new tab with a different name. then you will see online user list.you name is in pink, others are in green.

    userlist.png

  • Clike someone in the list, a dialog will pop up on the left bottom corner.
  • conversation.png

  • Write anything in and press enter. Then you are in a private conversation

I designed a funny thing in, delete all text in the dialog and input “black you” in low case. The person you are talking to will have a black screen with a funny face on for a few seconds.

Every colorful things you see in the webpage is written by javascript. There is no picture linked to the page. That is what i said Canvas in HTML5 can replace GDI+

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架