clockface: xml
This commit is contained in:
parent
423c9e9567
commit
7b3fb0f91c
@ -1,6 +1,8 @@
|
||||
package clockface
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
@ -11,13 +13,43 @@ type Point struct {
|
||||
Y float64
|
||||
}
|
||||
|
||||
const (
|
||||
secondHandLength = 90
|
||||
clockCentreX = 150
|
||||
clockCentreY = 150
|
||||
)
|
||||
|
||||
const svgStart = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="100%"
|
||||
height="100%"
|
||||
viewBox="0 0 300 300"
|
||||
version="2.0">`
|
||||
|
||||
const bezel = `<circle cx="150" cy="150" r="100" style="fill:#fff;stroke:#000;stroke-width:5px;"/>`
|
||||
|
||||
const svgEnd = `</svg>`
|
||||
|
||||
func SVGWriter(w io.Writer, t time.Time) {
|
||||
io.WriteString(w, svgStart)
|
||||
io.WriteString(w, bezel)
|
||||
SecondHand(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(t time.Time) Point {
|
||||
func SecondHand(w io.Writer, t time.Time) {
|
||||
p := secondHandPoint(t)
|
||||
p = Point{p.X * 90, p.Y * 90} // scale
|
||||
p = Point{p.X, -p.Y} // flip
|
||||
p = Point{p.X + 150, p.Y + 150} // translate
|
||||
return p
|
||||
p = Point{p.X * secondHandLength, p.Y * secondHandLength} // scale
|
||||
p = Point{p.X, -p.Y} // flip
|
||||
p = Point{p.X + clockCentreX, p.Y + clockCentreY} // translate
|
||||
fmt.Fprintf(
|
||||
w,
|
||||
`<line x1="150" y1="150" x2="%f" y2="%f" style="fill:none;stroke:#f00;stroke-width:3px;"/>`,
|
||||
p.X,
|
||||
p.Y,
|
||||
)
|
||||
}
|
||||
|
||||
func secondsInRadians(t time.Time) float64 {
|
||||
|
@ -1,28 +1,81 @@
|
||||
package clockface
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSecondHandAtMidnight(t *testing.T) {
|
||||
type Svg struct {
|
||||
XMLName xml.Name `xml:"svg"`
|
||||
Text string `xml:",chardata"`
|
||||
Xmlns string `xml:"xmlns,attr"`
|
||||
Width string `xml:"width,attr"`
|
||||
Height string `xml:"height,attr"`
|
||||
ViewBox string `xml:"viewBox,attr"`
|
||||
Version string `xml:"version,attr"`
|
||||
Circle struct {
|
||||
Text string `xml:",chardata"`
|
||||
Cx string `xml:"cx,attr"`
|
||||
Cy string `xml:"cy,attr"`
|
||||
R string `xml:"r,attr"`
|
||||
Style string `xml:"style,attr"`
|
||||
} `xml:"circle"`
|
||||
Line []struct {
|
||||
Text string `xml:",chardata"`
|
||||
X1 string `xml:"x1,attr"`
|
||||
Y1 string `xml:"y1,attr"`
|
||||
X2 string `xml:"x2,attr"`
|
||||
Y2 string `xml:"y2,attr"`
|
||||
Style string `xml:"style,attr"`
|
||||
} `xml:"line"`
|
||||
}
|
||||
|
||||
// func TestSecondHandAtMidnight(t *testing.T) {
|
||||
// tm := time.Date(1337, time.January, 1, 0, 0, 0, 0, time.UTC)
|
||||
//
|
||||
// want := Point{X: 150, Y: 150 - 90}
|
||||
// got := SecondHand(tm)
|
||||
//
|
||||
// if got != want {
|
||||
// t.Errorf("Got %v, wanted %v", got, want)
|
||||
// }
|
||||
// }
|
||||
|
||||
// func TestSecondHandAt30Seconds(t *testing.T) {
|
||||
// tm := time.Date(1337, time.January, 1, 0, 0, 30, 0, time.UTC)
|
||||
//
|
||||
// want := Point{X: 150, Y: 150 + 90}
|
||||
// got := SecondHand(tm)
|
||||
//
|
||||
// if got != want {
|
||||
// t.Errorf("Got %v, wanted %v", got, want)
|
||||
// }
|
||||
// }
|
||||
|
||||
func TestSVGWriterAtMidnight(t *testing.T) {
|
||||
tm := time.Date(1337, time.January, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
want := Point{X: 150, Y: 150 - 90}
|
||||
got := SecondHand(tm)
|
||||
b := bytes.Buffer{}
|
||||
SVGWriter(&b, tm)
|
||||
|
||||
if got != want {
|
||||
t.Errorf("Got %v, wanted %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSecondHandAt30Seconds(t *testing.T) {
|
||||
tm := time.Date(1337, time.January, 1, 0, 0, 30, 0, time.UTC)
|
||||
|
||||
want := Point{X: 150, Y: 150 + 90}
|
||||
got := SecondHand(tm)
|
||||
|
||||
if got != want {
|
||||
t.Errorf("Got %v, wanted %v", got, want)
|
||||
svg := Svg{}
|
||||
xml.Unmarshal(b.Bytes(), &svg)
|
||||
|
||||
x2 := "150.000000"
|
||||
y2 := "60.000000"
|
||||
|
||||
for _, line := range svg.Line {
|
||||
if line.X2 == x2 && line.Y2 == y2 {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
t.Errorf(
|
||||
"Expected to find the second hand with x2 of %+v and y2 of %+v, in the SVG output %v",
|
||||
x2,
|
||||
y2,
|
||||
b.String(),
|
||||
)
|
||||
}
|
||||
|
28
main.go
28
main.go
@ -1,9 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gobytest/clockface"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
@ -18,29 +16,5 @@ func main() {
|
||||
// clockface
|
||||
t := time.Now()
|
||||
|
||||
sh := clockface.SecondHand(t)
|
||||
io.WriteString(os.Stdout, svgStart)
|
||||
io.WriteString(os.Stdout, bezel)
|
||||
io.WriteString(os.Stdout, secondHandTag(sh))
|
||||
io.WriteString(os.Stdout, svgEnd)
|
||||
clockface.SVGWriter(os.Stdout, t)
|
||||
}
|
||||
|
||||
func secondHandTag(p clockface.Point) string {
|
||||
return fmt.Sprintf(
|
||||
`<line x1="150" y1="150" x2="%f" y2="%f" style="fill:none;stroke:#f00;stroke-width:3px;"/>`,
|
||||
p.X,
|
||||
p.Y,
|
||||
)
|
||||
}
|
||||
|
||||
const svgStart = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="100%"
|
||||
height="100%"
|
||||
viewBox="0 0 300 300"
|
||||
version="2.0">`
|
||||
|
||||
const bezel = `<circle cx="150" cy="150" r="100" style="fill:#fff;stroke:#000;stroke-width:5px;"/>`
|
||||
|
||||
const svgEnd = `</svg>`
|
||||
|
Loading…
Reference in New Issue
Block a user