Updated testing
Added svgWriter Refactored
This commit is contained in:
parent
09ccafb97b
commit
9a21ca4d26
5
.gitignore
vendored
5
.gitignore
vendored
@ -93,7 +93,6 @@ $RECYCLE.BIN/
|
|||||||
*.msix
|
*.msix
|
||||||
*.msm
|
*.msm
|
||||||
*.msp
|
*.msp
|
||||||
|
|
||||||
# Windows shortcuts
|
# Windows shortcuts
|
||||||
*.lnk
|
*.lnk
|
||||||
|
|
||||||
@ -102,4 +101,6 @@ $RECYCLE.BIN/
|
|||||||
# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)
|
# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
|
||||||
.idea
|
.idea
|
||||||
|
/clockface/clockface
|
||||||
|
*.svg
|
||||||
|
12
clockface.go
12
clockface.go
@ -5,23 +5,11 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const secondHandLength = 90
|
|
||||||
const clockCentreX = 150
|
|
||||||
const clockCentreY = 150
|
|
||||||
|
|
||||||
type Point struct {
|
type Point struct {
|
||||||
X float64
|
X float64
|
||||||
Y float64
|
Y float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func SecondHand(t time.Time) Point {
|
|
||||||
p := secondHandPoint(t)
|
|
||||||
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
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func secondsInRadians(t time.Time) float64 {
|
func secondsInRadians(t time.Time) float64 {
|
||||||
return math.Pi / (30 / (float64(t.Second())))
|
return math.Pi / (30 / (float64(t.Second())))
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"git.nerdfortress.dev/mitch/clockface"
|
"git.nerdfortress.dev/mitch/clockface"
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
sh := clockface.SecondHand(t)
|
clockface.SVGWriter(os.Stdout, t)
|
||||||
io.WriteString(os.Stdout, svgStart)
|
|
||||||
io.WriteString(os.Stdout, bezel)
|
|
||||||
io.WriteString(os.Stdout, secondHandTag(sh))
|
|
||||||
io.WriteString(os.Stdout, svgEnd)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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>`
|
|
||||||
|
@ -1,28 +1,55 @@
|
|||||||
package clockface
|
package clockface
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/xml"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"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 TestSVGWriterAtMidnight(t *testing.T) {
|
||||||
tm := time.Date(1337, time.January, 1, 0, 0, 0, 0, time.UTC)
|
tm := time.Date(1337, time.January, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
b := bytes.Buffer{}
|
||||||
|
|
||||||
want := Point{X: 150, Y: 150 - 90}
|
SVGWriter(&b, tm)
|
||||||
got := SecondHand(tm)
|
|
||||||
|
|
||||||
if got != want {
|
svg := Svg{}
|
||||||
t.Errorf("Got %v, want %v", got, want)
|
|
||||||
}
|
xml.Unmarshal(b.Bytes(), &svg)
|
||||||
}
|
|
||||||
|
x2 := "150.000"
|
||||||
func TestSecondHandAt30Seconds(t *testing.T) {
|
y2 := "60.000"
|
||||||
tm := time.Date(1337, time.January, 1, 0, 0, 30, 0, time.UTC)
|
|
||||||
|
for _, line := range svg.Line {
|
||||||
want := Point{X: 150, Y: 150 + 90}
|
if line.X2 == x2 && line.Y2 == y2 {
|
||||||
got := SecondHand(tm)
|
return
|
||||||
|
}
|
||||||
if got != want {
|
|
||||||
t.Errorf("Got %v, wanted %v", got, want)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
}
|
}
|
||||||
|
@ -6,14 +6,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func simpleTime(hours, minutes, seconds int) time.Time {
|
|
||||||
return time.Date(312, time.October, 28, hours, minutes, seconds, 0, time.UTC)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testName(t time.Time) string {
|
|
||||||
return t.Format("15:04:05")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSecondsInRadians(t *testing.T) {
|
func TestSecondsInRadians(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
time time.Time
|
time time.Time
|
||||||
@ -28,14 +20,14 @@ func TestSecondsInRadians(t *testing.T) {
|
|||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
t.Run(testName(c.time), func(t *testing.T) {
|
t.Run(testName(c.time), func(t *testing.T) {
|
||||||
got := secondsInRadians(c.time)
|
got := secondsInRadians(c.time)
|
||||||
if !roughlyEqualFloat64(got, c.angle) {
|
if got != c.angle {
|
||||||
t.Fatalf("Wanted %v radians, but got %v", c.angle, got)
|
t.Fatalf("Wanted %v radians, but got %v", c.angle, got)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSecondHandVector(t *testing.T) {
|
func TestSecondHandPoint(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
time time.Time
|
time time.Time
|
||||||
point Point
|
point Point
|
||||||
@ -63,3 +55,11 @@ func roughlyEqualPoint(a, b Point) bool {
|
|||||||
return roughlyEqualFloat64(a.X, b.X) &&
|
return roughlyEqualFloat64(a.X, b.X) &&
|
||||||
roughlyEqualFloat64(a.Y, b.Y)
|
roughlyEqualFloat64(a.Y, b.Y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func simpleTime(hours, minutes, seconds int) time.Time {
|
||||||
|
return time.Date(312, time.October, 28, hours, minutes, seconds, 0, time.UTC)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testName(t time.Time) string {
|
||||||
|
return t.Format("15:04:05")
|
||||||
|
}
|
||||||
|
39
svgWriter.go
Normal file
39
svgWriter.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package clockface
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const secondHandLength = 90
|
||||||
|
const clockCentreX = 150
|
||||||
|
const 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>`
|
||||||
|
|
||||||
|
//SVGWriter writes an SVG representation of an analog clock, showing the time t, to the writer w
|
||||||
|
func SVGWriter(w io.Writer, t time.Time) {
|
||||||
|
io.WriteString(w, svgStart)
|
||||||
|
io.WriteString(w, bezel)
|
||||||
|
SecondHand(w, t)
|
||||||
|
io.WriteString(w, svgEnd)
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
p = Point{p.X + clockCentreX, p.Y + clockCentreY} //translate
|
||||||
|
fmt.Fprintf(w, `<line x1="150" y1="150" x2="%.3f" y2="%.3f" style="fill:none;stroke:#f00;stroke-width:3px;"/>`, p.X, p.Y)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user