Skip to content

Commit

Permalink
💥 Breaking Change: *EntryとかGetImageとかにした
Browse files Browse the repository at this point in the history
- GetEntry returns *Entry (not Entry any more)
- Image renamed to GetImage
- Refactoring
  • Loading branch information
otiai10 committed Mar 15, 2021
1 parent 6401bfa commit 821ead5
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 35 deletions.
2 changes: 1 addition & 1 deletion cli/amesh.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func Amesh(r render.Renderer, geo, mask bool) error {
}

entry := amesh.GetEntry(now)
merged, err := entry.Image(geo, mask)
merged, err := entry.GetImage(geo, mask)
if err != nil {
return err
}
Expand Down
43 changes: 13 additions & 30 deletions cli/timelapse.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,16 @@ func Timelapse(r render.Renderer, minutes, delay int, loop bool) error {

fmt.Printf("直近%d分間の降雨画像を取得中", minutes)

snapshots, err := getSnapshots(time.Duration(minutes) * time.Minute)
now, err := getNow()
if err != nil {
return err
}

start := now.Add(time.Duration(-1*minutes) * time.Minute)
entries := amesh.GetEntries(start, now)

progress := func(i int) { fmt.Print(".") }
_, err = entries.GetImages(progress)
if err != nil {
return err
}
Expand All @@ -32,40 +41,14 @@ func Timelapse(r render.Renderer, minutes, delay int, loop bool) error {
fmt.Print("\033[s\033[H\033[1;32m")
}

length := len(snapshots)
for i := 0; true; i++ {
if i == length && !loop {
break
}
s := snapshots[i%length]
for _, entry := range entries {
moveCursorToTop()
r.Render(os.Stdout, s.Image)
fmt.Println(s.Time.String())
r.Render(os.Stdout, entry.Image)
fmt.Fprintln(os.Stdout, entry.Time.String())
time.Sleep(time.Duration(delay) * time.Millisecond)
}

fmt.Print("\033[0m")

return nil
}

func getSnapshots(dur time.Duration) (snapshots []snapshot, err error) {

now, err := getNow()
if err != nil {
return nil, err
}

sheets := int((int64(dur) / int64(5*time.Minute))) + 1
for i := 0; i < sheets; i++ {
t := now.Add(time.Duration(-5*(sheets-i)) * time.Minute)
entry := amesh.GetEntry(t)
img, err := entry.Image(true, true)
if err != nil {
return nil, err
}
snapshots = append(snapshots, snapshot{img, entry.Time})
fmt.Print(".")
}
return snapshots, nil
}
58 changes: 58 additions & 0 deletions lib/amesh/entries.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package amesh

import (
"image"
"image/color/palette"
"image/draw"
"image/gif"
"net/http"
"time"
)

// Entries ...
type Entries []*Entry

// GetEntries ...
func GetEntries(start, end time.Time) (entries Entries) {
t := truncateTime(start)
entries = append(entries, GetEntry(t))
for t := t.Add(unit); t.Before(end); t = t.Add(unit) {
entries = append(entries, GetEntry(t))
}
return
}

// ToImages ...
func (entries Entries) GetImages(progress func(int), client ...*http.Client) ([]*image.RGBA, error) {
images := make([]*image.RGBA, len(entries), len(entries))
for i, entry := range entries {
img, err := entry.GetImage(true, true, client...)
if err != nil {
return images, err
}
images[i] = img
if progress != nil {
progress(i)
}
}
return images, nil
}

// ToGif delay == msec
func (entries Entries) ToGif(delay int, loop bool) (*gif.GIF, error) {
dest := &gif.GIF{LoopCount: 5}
if loop {
dest.LoopCount = 0
}
images, err := entries.GetImages(nil)
if err != nil {
return nil, err
}
for _, img := range images {
paletted := image.NewPaletted(img.Bounds(), palette.Plan9)
draw.Draw(paletted, paletted.Bounds(), img, img.Bounds().Min, draw.Over)
dest.Image = append(dest.Image, paletted)
dest.Delay = append(dest.Delay, delay/10) // Because it's 100ths
}
return dest, err
}
19 changes: 15 additions & 4 deletions lib/amesh/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ const (
defaultLocation = "Asia/Tokyo"
)

// オンメモリ固定画像キャッシュ
var cache = map[string]image.Image{}

// Entry ...
type Entry struct {
URL string `json:"url"`
Expand All @@ -35,12 +38,13 @@ type Entry struct {
Time time.Time `json:"time"`

IsRainingFunc func(image.Image) (bool, error)
Image *image.RGBA
}

// GetEntry ...
func GetEntry(t time.Time) Entry {
func GetEntry(t time.Time) *Entry {
t = truncateTime(t)
return Entry{
return &Entry{
URL: AmeshURL,
Map: getMap(),
Mesh: getMesh(t),
Expand All @@ -66,7 +70,7 @@ func getMesh(t time.Time) string {
}

// Image fetches image data from URL and merge them if needed.
func (entry Entry) Image(geo, mask bool, client ...*http.Client) (*image.RGBA, error) {
func (entry *Entry) GetImage(geo, mask bool, client ...*http.Client) (*image.RGBA, error) {

// If client not specified, use default HTTP client.
// This is because, for example, Google App Engine requires HTTP client with context.
Expand Down Expand Up @@ -99,10 +103,14 @@ func (entry Entry) Image(geo, mask bool, client ...*http.Client) (*image.RGBA, e
draw.Draw(merged, masklayer.Bounds(), masklayer, image.Point{0, 0}, 0)
}

entry.Image = merged
return merged, nil
}

func (entry Entry) getImageFor(imgurl string, client *http.Client) (image.Image, error) {
func (entry *Entry) getImageFor(imgurl string, client *http.Client) (image.Image, error) {
if cached, ok := cache[imgurl]; ok {
return cached, nil
}
res, err := client.Get(imgurl)
if err != nil {
return nil, err
Expand All @@ -112,9 +120,11 @@ func (entry Entry) getImageFor(imgurl string, client *http.Client) (image.Image,
return nil, fmt.Errorf(res.Status)
}
img, _, err := image.Decode(res.Body)
cache[imgurl] = img
return img, err
}

/* FIXME: You ain't gonna need it
// IsRaining ...
func (entry *Entry) IsRaining(cliet *http.Client) (bool, error) {
Expand Down Expand Up @@ -151,3 +161,4 @@ func (entry *Entry) IsRaining(cliet *http.Client) (bool, error) {
return false, nil
}
*/

0 comments on commit 821ead5

Please sign in to comment.