aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristine Dodrill <me@christine.website>2018-10-09 19:43:02 -0700
committerChristine Dodrill <me@christine.website>2018-10-09 19:43:02 -0700
commit2ab3582aabeffe8c313152e833632d73a1461fbb (patch)
treeb41fe5a79844077d2412d0496d76cc2bb053cb2d
parentba39332adc24e98a9f96976736457a3ea6d6c46e (diff)
downloadx-2ab3582aabeffe8c313152e833632d73a1461fbb.tar.xz
x-2ab3582aabeffe8c313152e833632d73a1461fbb.zip
internal: package mainsa
-rw-r--r--internal/mainsa/cmd/mainsanow/main.go21
-rw-r--r--internal/mainsa/date.go128
-rw-r--r--internal/mainsa/date_test.go69
-rw-r--r--internal/mainsa/doc.go3
-rw-r--r--internal/mainsa/nanpa_string.go17
-rw-r--r--internal/mainsa/sike_string.go17
-rw-r--r--internal/mainsa/tawa_string.go17
7 files changed, 272 insertions, 0 deletions
diff --git a/internal/mainsa/cmd/mainsanow/main.go b/internal/mainsa/cmd/mainsanow/main.go
new file mode 100644
index 0000000..cd63a79
--- /dev/null
+++ b/internal/mainsa/cmd/mainsanow/main.go
@@ -0,0 +1,21 @@
+package main
+
+import (
+ "flag"
+ "log"
+ "time"
+
+ "github.com/Xe/x/internal"
+ "github.com/Xe/x/internal/mainsa"
+)
+
+func main() {
+ flag.Parse()
+ internal.HandleLicense()
+
+ tn, err := mainsa.At(time.Now())
+ if err != nil {
+ log.Fatal(err)
+ }
+ log.Printf("%s", tn)
+}
diff --git a/internal/mainsa/date.go b/internal/mainsa/date.go
new file mode 100644
index 0000000..418c8b2
--- /dev/null
+++ b/internal/mainsa/date.go
@@ -0,0 +1,128 @@
+package mainsa
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+)
+
+const (
+ sunoLen = 8 * time.Hour
+ linjaLen = sunosInLinja * sunoLen
+ sikeLen = linjasInSike * linjaLen
+ tawaLen = sikesInTawa * sikeLen
+ suliLen = tawasInSuli * tawaLen
+)
+
+const (
+ sunosInLinja = 3
+ linjasInSike = 3
+ sikesInTawa = 3
+ tawasInSuli = 4
+
+ sunosInSike = sunosInLinja * linjasInSike
+ sunosInTawa = sunosInSike * sikesInTawa
+ sunosInSuli = sunosInTawa * tawasInSuli
+)
+
+//go:generate stringer -type=Tawa
+
+// Tawa is a set of 3 cycles, or a season.
+type Tawa int
+
+// The four tawas of a year.
+const (
+ Kasi Tawa = 1 + iota
+ Seli
+ Sin
+ Lete
+)
+
+//go:generate stringer -type=Sike
+
+// Sike is a set of 3 threads, or a month.
+type Sike int
+
+// The three sikes.
+const (
+ Kama Sike = 1 + iota
+ Poka
+ Monsi
+)
+
+//go:generate stringer -type=Nanpa
+
+// Nanpa is a generic toki pona number
+type Nanpa int
+
+// Numbers
+const (
+ Wan Nanpa = 1 + iota
+ Tu
+ Mute
+)
+
+// TenpoNimi is the name of a given time. The remainder time is given as a time.Duration and should be shown in hour:minute format using time constant "3:04".
+type TenpoNimi struct {
+ Year int // suli
+ Season Tawa // tawa
+ Month Sike // sike
+ Week Nanpa // linja
+ Day Nanpa // suno
+ Remainder time.Duration
+}
+
+func awen(d time.Duration) string {
+ return fmt.Sprintf("%d:%02d", int(d.Hours()), int(d.Minutes())%60)
+}
+
+func (tn TenpoNimi) String() string {
+ return strings.ToLower(fmt.Sprintf(
+ "suli %d tawa %s sike %s linja %s suno %s awen %s",
+ tn.Year,
+ tn.Season,
+ tn.Month,
+ tn.Week,
+ tn.Day,
+ awen(tn.Remainder),
+ ))
+}
+
+const zeroDateUnix = 1538870400
+
+// YearZero is the arbitrary anchor date from plane 432 to ma Insa year 1 planting season, coming cycle, first week, first day..
+var YearZero = time.Unix(zeroDateUnix, 0)
+
+// Errors
+var (
+ ErrBeforeEpoch = errors.New("mainsa: time before zero date")
+)
+
+// At returns the time in ma Insa for a given Go time.
+func At(t time.Time) (TenpoNimi, error) {
+ if t.Before(YearZero) {
+ return TenpoNimi{}, ErrBeforeEpoch
+ }
+
+ dur := t.Sub(YearZero)
+
+ var linjas = int(dur / linjaLen) // week => 3 days
+ var sikes = int(dur / sikeLen) // month => 3 weeks
+ var tawas = int(dur / tawaLen) // season => 3 months
+ var sulis = int(dur / suliLen) // year => 4 seasons
+ sunosd := float64(dur) / float64(sunoLen)
+ sunos := int(sunosd)
+ rem := time.Duration((sunosd - float64(sunos)) * float64(sunoLen)).Round(time.Minute)
+
+ result := TenpoNimi{
+ Year: sulis,
+ Season: Tawa(tawas%tawasInSuli) + 1,
+ Month: Sike(sikes%sikesInTawa) + 1,
+ Week: Nanpa(linjas%linjasInSike) + 1,
+ Day: Nanpa(sunos%sunosInLinja) + 1,
+ Remainder: rem,
+ }
+
+ return result, nil
+}
diff --git a/internal/mainsa/date_test.go b/internal/mainsa/date_test.go
new file mode 100644
index 0000000..0d5c5d8
--- /dev/null
+++ b/internal/mainsa/date_test.go
@@ -0,0 +1,69 @@
+package mainsa
+
+import (
+ "testing"
+ "time"
+)
+
+func TestSuliLen(t *testing.T) {
+ if suliLen != sunosInSuli*sunoLen {
+ t.Fatalf("expected a year to be %d sunos, got: %d sunos", sunosInSuli, suliLen/sunoLen)
+ }
+
+ t.Logf("%d sunos in linja", sunosInLinja)
+ t.Logf("%d sunos in sike", sunosInSike)
+ t.Logf("%d sunos in tawa", sunosInTawa)
+ t.Logf("%d sunos in suli", sunosInSuli)
+}
+
+func TestAt(t *testing.T) {
+ cases := []struct {
+ name string
+ inp time.Time
+ wantErr bool
+ outp TenpoNimi
+ }{
+ {
+ name: "before",
+ inp: YearZero.Add(-1 * time.Hour),
+ wantErr: true,
+ },
+ {
+ name: "second_day",
+ inp: YearZero.Add(sunoLen),
+ outp: TenpoNimi{
+ Year: 0,
+ Season: Kasi,
+ Month: Kama,
+ Week: Wan,
+ Day: Tu,
+ Remainder: time.Duration(0),
+ },
+ },
+ }
+
+ for _, cs := range cases {
+ t.Run(cs.name, func(t *testing.T) {
+ tn, err := At(cs.inp)
+ if err != nil && !cs.wantErr {
+ t.Fatal(err)
+ }
+
+ if cs.wantErr && err == nil {
+ t.Fatal("wanted an error but got none")
+ }
+
+ if cs.wantErr {
+ return
+ }
+
+ cts := cs.outp.String()
+ tts := tn.String()
+ t.Logf("expected: %s", cts)
+ t.Logf("got: %s", tts)
+ if cts != tts {
+ t.Fatal("see -v")
+ }
+ })
+ }
+}
diff --git a/internal/mainsa/doc.go b/internal/mainsa/doc.go
new file mode 100644
index 0000000..738db0d
--- /dev/null
+++ b/internal/mainsa/doc.go
@@ -0,0 +1,3 @@
+// Package mainsa is a small set of conversion or other useful utility functions
+// for converting plane 432 units to ma Insa units.
+package mainsa
diff --git a/internal/mainsa/nanpa_string.go b/internal/mainsa/nanpa_string.go
new file mode 100644
index 0000000..4c66a58
--- /dev/null
+++ b/internal/mainsa/nanpa_string.go
@@ -0,0 +1,17 @@
+// Code generated by "stringer -type=Nanpa"; DO NOT EDIT.
+
+package mainsa
+
+import "strconv"
+
+const _Nanpa_name = "WanTuMute"
+
+var _Nanpa_index = [...]uint8{0, 3, 5, 9}
+
+func (i Nanpa) String() string {
+ i -= 1
+ if i < 0 || i >= Nanpa(len(_Nanpa_index)-1) {
+ return "Nanpa(" + strconv.FormatInt(int64(i+1), 10) + ")"
+ }
+ return _Nanpa_name[_Nanpa_index[i]:_Nanpa_index[i+1]]
+}
diff --git a/internal/mainsa/sike_string.go b/internal/mainsa/sike_string.go
new file mode 100644
index 0000000..9bc2a92
--- /dev/null
+++ b/internal/mainsa/sike_string.go
@@ -0,0 +1,17 @@
+// Code generated by "stringer -type=Sike"; DO NOT EDIT.
+
+package mainsa
+
+import "strconv"
+
+const _Sike_name = "KamaPokaMonsi"
+
+var _Sike_index = [...]uint8{0, 4, 8, 13}
+
+func (i Sike) String() string {
+ i -= 1
+ if i < 0 || i >= Sike(len(_Sike_index)-1) {
+ return "Sike(" + strconv.FormatInt(int64(i+1), 10) + ")"
+ }
+ return _Sike_name[_Sike_index[i]:_Sike_index[i+1]]
+}
diff --git a/internal/mainsa/tawa_string.go b/internal/mainsa/tawa_string.go
new file mode 100644
index 0000000..37d2da6
--- /dev/null
+++ b/internal/mainsa/tawa_string.go
@@ -0,0 +1,17 @@
+// Code generated by "stringer -type=Tawa"; DO NOT EDIT.
+
+package mainsa
+
+import "strconv"
+
+const _Tawa_name = "KasiSeliSinLete"
+
+var _Tawa_index = [...]uint8{0, 4, 8, 11, 15}
+
+func (i Tawa) String() string {
+ i -= 1
+ if i < 0 || i >= Tawa(len(_Tawa_index)-1) {
+ return "Tawa(" + strconv.FormatInt(int64(i+1), 10) + ")"
+ }
+ return _Tawa_name[_Tawa_index[i]:_Tawa_index[i+1]]
+}