From 469855f3de98b717a9d673a055ff5f2f39c776ab Mon Sep 17 00:00:00 2001 From: mitch Date: Wed, 19 Jan 2022 23:26:08 -0500 Subject: [PATCH] First commit --- .gitignore | 105 +++++++++++++++++++++++++++++++++++ clockface.go | 1 + clockface/main.go | 42 ++++++++++++++ clockface_acceptance_test.go | 35 ++++++++++++ clockface_test.go | 73 ++++++++++++++++++++++++ go.mod | 3 + 6 files changed, 259 insertions(+) create mode 100644 .gitignore create mode 100644 clockface.go create mode 100644 clockface/main.go create mode 100644 clockface_acceptance_test.go create mode 100644 clockface_test.go create mode 100644 go.mod diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..085f9fd --- /dev/null +++ b/.gitignore @@ -0,0 +1,105 @@ +# File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig + +# Created by https://www.gitignore.io/api/macos,visualstudiocode,terraform,windows +# Edit at https://www.gitignore.io/?templates=macos,visualstudiocode,terraform,windows + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Terraform ### +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* +*.plan + +# Crash log files +crash.log + +# Ignore any .tfvars files that are generated automatically for each Terraform run. Most +# .tfvars files are managed as part of configuration and so should be included in +# version control. +# +# example.tfvars + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json +secrets.tfvars + +# Include override files you do wish to add to version control using negated pattern +# +# !example_override.tf + +### VisualStudioCode ### +.vscode/* +#!.vscode/settings.json +#!.vscode/tasks.json +#!.vscode/launch.json +#!.vscode/extensions.json + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.gitignore.io/api/macos,visualstudiocode,terraform,windows + +# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option) +.vscode/* + +.idea \ No newline at end of file diff --git a/clockface.go b/clockface.go new file mode 100644 index 0000000..1c65078 --- /dev/null +++ b/clockface.go @@ -0,0 +1 @@ +package clockface diff --git a/clockface/main.go b/clockface/main.go new file mode 100644 index 0000000..8a191a2 --- /dev/null +++ b/clockface/main.go @@ -0,0 +1,42 @@ +package clockface + +import ( + "math" + "time" +) + +package clockface + +import ( +"git.nerdfortress.dev/mitch/gotdd/clockface" +"math" +"time" +) + +const secondHandLength = 90 +const clockCentreX = 150 +const clockCentreY = 150 + +type Point struct { + X 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 { + return math.Pi / (30 / (float64(t.Second()))) +} + +func secondHandPoint(t time.Time) Point { + angle := secondsInRadians(t) + x := math.Sin(angle) + y := math.Cos(angle) + return Point{x, y} +} diff --git a/clockface_acceptance_test.go b/clockface_acceptance_test.go new file mode 100644 index 0000000..b559a89 --- /dev/null +++ b/clockface_acceptance_test.go @@ -0,0 +1,35 @@ +package clockface + +import ( + "testing" + "time" +) + +package clockface + +import ( +"testing" +"time" +) + +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, want %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) + } +} diff --git a/clockface_test.go b/clockface_test.go new file mode 100644 index 0000000..150405f --- /dev/null +++ b/clockface_test.go @@ -0,0 +1,73 @@ +package clockface + +import ( + "math" + "testing" + "time" +) + +package clockface + +import ( +"math" +"testing" +"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) { + cases := []struct { + time time.Time + angle float64 + }{ + {simpleTime(0, 0, 30), math.Pi}, + {simpleTime(0, 0, 0), 0}, + {simpleTime(0, 0, 45), (math.Pi / 2) * 3}, + {simpleTime(0, 0, 7), (math.Pi / 30) * 7}, + } + + for _, c := range cases { + t.Run(testName(c.time), func(t *testing.T) { + got := secondsInRadians(c.time) + if !roughlyEqualFloat64(got, c.angle) { + t.Fatalf("Wanted %v radians, but got %v", c.angle, got) + } + }) + } +} + +func TestSecondHandVector(t *testing.T) { + cases := []struct { + time time.Time + point Point + }{ + {simpleTime(0, 0, 30), Point{0, -1}}, + {simpleTime(0, 0, 45), Point{-1, 0}}, + } + + for _, c := range cases { + t.Run(testName(c.time), func(t *testing.T) { + got := secondHandPoint(c.time) + if !roughlyEqualPoint(got, c.point) { + t.Fatalf("Wanted %v Point, but got %v", c.point, got) + } + }) + } +} + +func roughlyEqualFloat64(a, b float64) bool { + const equalityThreshold = 1e-7 + return math.Abs(a-b) < equalityThreshold +} + +func roughlyEqualPoint(a, b Point) bool { + return roughlyEqualFloat64(a.X, b.X) && + roughlyEqualFloat64(a.Y, b.Y) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..a3e606e --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module clockface + +go 1.17