clockface: add minute hand tests
This commit is contained in:
parent
5a62fef4f3
commit
a4531bde4c
@ -14,6 +14,7 @@ type Point struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
minuteHandLength = 80
|
||||||
secondHandLength = 90
|
secondHandLength = 90
|
||||||
clockCentreX = 150
|
clockCentreX = 150
|
||||||
clockCentreY = 150
|
clockCentreY = 150
|
||||||
@ -34,12 +35,13 @@ const svgEnd = `</svg>`
|
|||||||
func SVGWriter(w io.Writer, t time.Time) {
|
func SVGWriter(w io.Writer, t time.Time) {
|
||||||
io.WriteString(w, svgStart)
|
io.WriteString(w, svgStart)
|
||||||
io.WriteString(w, bezel)
|
io.WriteString(w, bezel)
|
||||||
SecondHand(w, t)
|
secondHand(w, t)
|
||||||
|
minuteHand(w, t)
|
||||||
io.WriteString(w, svgEnd)
|
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
|
// 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) {
|
func secondHand(w io.Writer, t time.Time) {
|
||||||
p := secondHandPoint(t)
|
p := secondHandPoint(t)
|
||||||
p = Point{p.X * secondHandLength, p.Y * secondHandLength} // scale
|
p = Point{p.X * secondHandLength, p.Y * secondHandLength} // scale
|
||||||
p = Point{p.X, -p.Y} // flip
|
p = Point{p.X, -p.Y} // flip
|
||||||
@ -52,30 +54,39 @@ func SecondHand(w io.Writer, t time.Time) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
p = Point{p.X * minuteHandLength, p.Y * minuteHandLength} // 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 minutesInRadians(t time.Time) float64 {
|
func minutesInRadians(t time.Time) float64 {
|
||||||
return (secondsInRadians(t) / 60) + math.Pi/(30/float64(t.Minute()))
|
return (secondsInRadians(t) / 60) + math.Pi/(30/float64(t.Minute()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func minuteHandPoint(t time.Time) Point {
|
func minuteHandPoint(t time.Time) Point {
|
||||||
angle := minutesInRadians(t)
|
return angleToPoint(minutesInRadians(t))
|
||||||
x := math.Sin(angle)
|
|
||||||
y := math.Cos(angle)
|
|
||||||
|
|
||||||
return Point{x, y}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func secondsInRadians(t time.Time) float64 {
|
func secondsInRadians(t time.Time) float64 {
|
||||||
// XXX:Wanted 3.141592653589793 radians, but got 3.1415926535897936
|
|
||||||
// return float64(t.Second()) * (math.Pi / 30)
|
|
||||||
|
|
||||||
return math.Pi / (30 / float64(t.Second()))
|
return math.Pi / (30 / float64(t.Second()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func secondHandPoint(t time.Time) Point {
|
func secondHandPoint(t time.Time) Point {
|
||||||
angle := secondsInRadians(t)
|
return angleToPoint(secondsInRadians(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
func angleToPoint(angle float64) Point {
|
||||||
x := math.Sin(angle)
|
x := math.Sin(angle)
|
||||||
y := math.Cos(angle)
|
y := math.Cos(angle)
|
||||||
|
|
||||||
// XXX: Wanted {0 -1} Point, but got {1.2246467991473515e-16 -1}
|
|
||||||
return Point{x, y}
|
return Point{x, y}
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,34 @@ func TestSVGWriterSecondHand(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSVGWriterMinuteHand(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
time time.Time
|
||||||
|
line Line
|
||||||
|
}{
|
||||||
|
{simpleTime(0, 0, 0), Line{150, 150, 150, 70}},
|
||||||
|
// {simpleTime(0, 0, 30), Line{150, 150, 150, 240}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range cases {
|
||||||
|
t.Run(testName(c.time), func(t *testing.T) {
|
||||||
|
b := bytes.Buffer{}
|
||||||
|
SVGWriter(&b, c.time)
|
||||||
|
|
||||||
|
svg := Svg{}
|
||||||
|
xml.Unmarshal(b.Bytes(), &svg)
|
||||||
|
|
||||||
|
if !containsLine(c.line, svg.Line) {
|
||||||
|
t.Errorf(
|
||||||
|
"Expected to find the minute hand line %+v in the SVG lines %v",
|
||||||
|
c.line,
|
||||||
|
svg.Line,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func containsLine(l Line, ls []Line) bool {
|
func containsLine(l Line, ls []Line) bool {
|
||||||
for _, line := range ls {
|
for _, line := range ls {
|
||||||
if line == l {
|
if line == l {
|
||||||
|
Loading…
Reference in New Issue
Block a user