How to resolve the algorithm Draw a clock step by step in the Go programming language

Published on 12 May 2024 09:40 PM
#Go

How to resolve the algorithm Draw a clock step by step in the Go programming language

Table of Contents

Problem Statement

Draw a clock.

More specific:

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Draw a clock step by step in the Go programming language

The provided Go code implements a simple web server that displays an interactive clock using the WebSocket protocol for real-time updates. Here's a detailed explanation of the code:

  1. Package and Imports:

    • package main: The main program package.
    • It imports various libraries, including golang.org/x/net/websocket for handling WebSockets, flag for command-line argument parsing, fmt, html/template for template rendering, io, math, net/http, and time.
  2. Variables:

    • Portnum: Stores the port number on which the server will listen for incoming connections.
    • Hostsite: Stores the hostname or IP address where the server will be hosted.
  3. Structs:

    • PageSettings: A struct that holds the host and port information for the WebSocket connection.
  4. Constants:

    • Canvaswidth and Canvasheight: Define the dimensions of the clock's canvas in pixels (512x512).
    • Color constants: HourColor, MinuteColor, and SecondColor define the colors used for drawing the hour, minute, and second hands, respectively.
  5. Main Function:

    • Parses command-line arguments for Port and Site using the flag package.
    • Sets up HTTP route handlers for the root URL ("/") and the WebSocket endpoint ("/ws").
    • Starts the HTTP server on the specified port and host using http.ListenAndServe.
  6. HTTP Handler:

    • webhandler handles HTTP requests to the root URL.
    • It renders a template called "clock.html," which contains the HTML and JavaScript code for displaying the clock.
  7. WebSocket Handler:

    • wshandle handles WebSocket connections.
    • It enters an infinite loop where it continuously reads the current time and updates the position of the hour, minute, and second hands on the clock.
    • It uses the HourCords, MinSecCords, and fmt.Sprintf functions to calculate the coordinates for drawing the hands and sends them as a message to the connected client.
  8. Coordinate Calculation Functions:

    • MinSecCords and HourCords: These functions calculate the coordinates for the endpoints of the minute, second, and hour hands, respectively, based on the current time. They take the time value (in minutes or hours) and the radius of the clock as inputs.
  9. HTML Template:

    • The HTML template clock.html defines the web page that displays the clock.
    • It includes JavaScript code that establishes a WebSocket connection to the server and handles incoming messages to draw the hands of the clock.
  10. JavaScript Code:

  • The JavaScript code in the HTML template:
    • Connects to the WebSocket server using new WebSocket().
    • On successful connection, sends a "READY" message to the server.
    • Listens for incoming messages from the server and handles them by parsing the data and drawing the clock hands accordingly.
    • Renders lines on the specified canvas based on the received coordinates and color.

Source code in the go programming language

package main

import (
	"golang.org/x/net/websocket"
	"flag"
	"fmt"
	"html/template"
	"io"
	"math"
	"net/http"
	"time"
)

var (
	Portnum  string
	Hostsite string
)

type PageSettings struct {
	Host string
	Port string
}

const (
	Canvaswidth  = 512
	Canvasheight = 512
	//color constants
	HourColor   = "#ff7373" // pinkish
	MinuteColor = "#00b7e4" //light blue
	SecondColor = "#b58900" //gold
)

func main() {
	flag.StringVar(&Portnum, "Port", "1234", "Port to host server.")
	flag.StringVar(&Hostsite, "Site", "localhost", "Site hosting server")
	flag.Parse()
	http.HandleFunc("/", webhandler)
	http.Handle("/ws", websocket.Handler(wshandle))
	err := http.ListenAndServe(Hostsite+":"+Portnum, nil)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("server running")
}

func webhandler(w http.ResponseWriter, r *http.Request) {
	wsurl := PageSettings{Host: Hostsite, Port: Portnum}
	template, _ := template.ParseFiles("clock.html")
	template.Execute(w, wsurl)
}

//Given a websocket connection,
//serves updating time function
func wshandle(ws *websocket.Conn) {
	for {
		hour, min, sec := time.Now().Clock()
		hourx, houry := HourCords(hour, Canvasheight/2)
		minx, miny := MinSecCords(min, Canvasheight/2)
		secx, secy := MinSecCords(sec, Canvasheight/2)
		msg := "CLEAR\n"
		msg += fmt.Sprintf("HOUR %d %d %s\n", hourx, houry, HourColor)
		msg += fmt.Sprintf("MIN %d %d %s\n", minx, miny, MinuteColor)
		msg += fmt.Sprintf("SEC %d %d %s", secx, secy, SecondColor)
		io.WriteString(ws, msg)
		time.Sleep(time.Second / 60.0)
	}
}

//Given current minute or second time(i.e 30 min, 60 minutes)
//and the radius, returns pair of cords to draw line to
func MinSecCords(ctime int, radius int) (int, int) {
	//converts min/sec to angle and then to radians

	theta := ((float64(ctime)*6 - 90) * (math.Pi / 180))
	x := float64(radius) * math.Cos(theta)
	y := float64(radius) * math.Sin(theta)
	return int(x) + 256, int(y) + 256
}

//Given current hour time(i.e. 12, 8) and the radius,
//returns pair of cords to draw line to
func HourCords(ctime int, radius int) (int, int) {
	//converts hours to angle and then to radians
	theta := ((float64(ctime)*30 - 90) * (math.Pi / 180))
	x := float64(radius) * math.Cos(theta)
	y := float64(radius) * math.Sin(theta)
	return int(x) + 256, int(y) + 256
}


<!DOCTYPE html>
<meta charset="utf-8" />
<title>Clock</title>
<script language="javascript" type="text/javascript">

  var connurl = "ws://{{.Host}}:{{.Port}}/ws";
  //var ctx;
  var secondhand;
  var minutehand;
  var hourhand;
  function wsConnect()
  {
	//get contexts for drawing
    //var canvas = document.getElementById( "canvas" );
    //ctx = canvas.getContext( '2d' );
	var canvas = document.getElementById("rim");
    //draw circle for rim
    rim =  canvas.getContext('2d');
    rim.beginPath();
    rim.arc(256,256,256,0,2*Math.PI);
    rim.stroke();
    //minute hand
    canvas = document.getElementById("minutehand");
    minutehand = canvas.getContext('2d');
    //hour hand
    canvas = document.getElementById("hourhand");
    hourhand = canvas.getContext('2d');
    //second hand
    canvas = document.getElementById("secondhand");
    secondhand = canvas.getContext('2d');

    ws = new WebSocket( connurl );
    ws.onopen = function( e ) {
      console.log( "CONNECTED" );
      ws.send( "READY" );
    };
    /*ws.onclose = function( e ) { 
      console.log( "DISCONNECTED" );
    };*/
    ws.onmessage = function( e ) {
      var data = e.data.split("\n");
      for ( var line in data ) {
        var msg = data[line].split(" ");
        var cmd = msg[0];
        if (cmd =="CLEAR"){
          minutehand.clearRect(0,0,512,512);
          secondhand.clearRect(0,0,512,512);
          hourhand.clearRect(0,0,512,512);
        }else if (cmd === "HOUR"){
          renderline(hourhand, msg);
        }else if (cmd === "MIN"){
          renderline(minutehand, msg);
        }else if (cmd === "SEC"){
          renderline(secondhand, msg);
        }else if (cmd ===""){
          cmd = "";
        }else{
          console.log("BAD COMMAND: "+cmd + "; "+msg);
        }
      }
    };
    ws.onerror = function( e ) {
      console.log( 'WS Error: ' + e.data );
    };
  }
  //render line given paramets
  function renderline(ctx, msg){
    ctx.clearRect(0,0,512,512);
    ctx.width = ctx.width;
    var x = parseInt(msg[1],10);
    var y = parseInt(msg[2],10);
    var color = msg[3];
    ctx.strokeStyle = color;
    ctx.beginPath();
    ctx.moveTo(256,256);
    ctx.lineTo(x,y);
    ctx.stroke();
  }

  window.addEventListener( "load", wsConnect, false );

</script>

<body>
    <h2>Clock</h2>
	
  <canvas id="rim" width="512" height="512" style="position: absolute; left: 0; top: 0; z-index: 0;">
        Sorry, your browser does not support Canvas
  </canvas>
	<canvas id="hourhand" width="512" height="512"style="position: absolute; left: 0; top: 0; z-index: 1;">
        Sorry, your browser does not support Canvas
  </canvas>
	<canvas id="minutehand" width="512" height="512"style="position: absolute; left: 0; top: 0; z-index: 2;">
        Sorry, your browser does not support Canvas
  </canvas>
	<canvas id="secondhand" width="512" height="512"style="position: absolute; left: 0; top: 0; z-index: 3;">
        Sorry, your browser does not support Canvas
  </canvas>
	
</body>
</html>


  

You may also check:How to resolve the algorithm Empty program step by step in the COBOL programming language
You may also check:How to resolve the algorithm Loops/Nested step by step in the SPL programming language
You may also check:How to resolve the algorithm EKG sequence convergence step by step in the REXX programming language
You may also check:How to resolve the algorithm Scope/Function names and labels step by step in the Ring programming language
You may also check:How to resolve the algorithm Amb step by step in the D programming language