package clockface import ( "fmt" "io" "math" "time" ) // Point represents a two-dimentional Cartesian coordinate type Point struct { X float64 Y float64 } const ( hourHandLength = 50 minuteHandLength = 80 secondHandLength = 90 clockCentreX = 150 clockCentreY = 150 ) const ( secondsInHalfClock = 30 secondsInClock = 2 * secondsInHalfClock minutesInHalfClock = 30 minutesInClock = 2 * minutesInHalfClock hoursInHalfClock = 6 hoursInClock = 2 * hoursInHalfClock ) const svgStart = ` ` const bezel = `` const svgEnd = `` func SVGWriter(w io.Writer, t time.Time) { io.WriteString(w, svgStart) io.WriteString(w, bezel) secondHand(w, t) minuteHand(w, t) hourHand(w, t) io.WriteString(w, svgEnd) } // SecondHand is the unit vector of the second hand of an analogue clock at the time `t` represented as a Point func secondHand(w io.Writer, t time.Time) { p := secondHandPoint(t) makeHand(w, secondHandLength, p) } // MinuteHand is the unit vector of the minute hand of an analogue clock at the time `t` represented as a Point func minuteHand(w io.Writer, t time.Time) { p := minuteHandPoint(t) makeHand(w, minuteHandLength, p) } // MinuteHand is the unit vector of the minute hand of an analogue clock at the time `t` represented as a Point func hourHand(w io.Writer, t time.Time) { p := hourHandPoint(t) makeHand(w, hourHandLength, p) } func makeHand(w io.Writer, length float64, p Point) { p = Point{p.X * length, p.Y * length} // scale p = Point{p.X, -p.Y} // flip p = Point{p.X + clockCentreX, p.Y + clockCentreY} // translate fmt.Fprintf( w, ``, p.X, p.Y, ) } func hoursInRadians(t time.Time) float64 { return (minutesInRadians(t) / hoursInClock) + math.Pi/(hoursInHalfClock/float64(t.Hour()%hoursInClock)) } func hourHandPoint(t time.Time) Point { return angleToPoint(hoursInRadians(t)) } func minutesInRadians(t time.Time) float64 { return (secondsInRadians(t) / minutesInClock) + math.Pi/(minutesInHalfClock/float64(t.Minute())) } func minuteHandPoint(t time.Time) Point { return angleToPoint(minutesInRadians(t)) } func secondsInRadians(t time.Time) float64 { return math.Pi / (secondsInHalfClock / float64(t.Second())) } func secondHandPoint(t time.Time) Point { return angleToPoint(secondsInRadians(t)) } func angleToPoint(angle float64) Point { x := math.Sin(angle) y := math.Cos(angle) return Point{x, y} }