clockface: add minute hand tests

This commit is contained in:
vinchent 2024-09-23 22:16:06 +02:00
parent 5a62fef4f3
commit a4531bde4c
2 changed files with 51 additions and 12 deletions

View File

@ -14,6 +14,7 @@ type Point struct {
}
const (
minuteHandLength = 80
secondHandLength = 90
clockCentreX = 150
clockCentreY = 150
@ -34,12 +35,13 @@ const svgEnd = `</svg>`
func SVGWriter(w io.Writer, t time.Time) {
io.WriteString(w, svgStart)
io.WriteString(w, bezel)
SecondHand(w, t)
secondHand(w, t)
minuteHand(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) {
func secondHand(w io.Writer, t time.Time) {
p := secondHandPoint(t)
p = Point{p.X * secondHandLength, p.Y * secondHandLength} // scale
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 {
return (secondsInRadians(t) / 60) + math.Pi/(30/float64(t.Minute()))
}
func minuteHandPoint(t time.Time) Point {
angle := minutesInRadians(t)
x := math.Sin(angle)
y := math.Cos(angle)
return Point{x, y}
return angleToPoint(minutesInRadians(t))
}
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()))
}
func secondHandPoint(t time.Time) Point {
angle := secondsInRadians(t)
return angleToPoint(secondsInRadians(t))
}
func angleToPoint(angle float64) Point {
x := math.Sin(angle)
y := math.Cos(angle)
// XXX: Wanted {0 -1} Point, but got {1.2246467991473515e-16 -1}
return Point{x, y}
}

View File

@ -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 {
for _, line := range ls {
if line == l {