Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
eraac committed Dec 5, 2017
1 parent b9b09fc commit e829090
Show file tree
Hide file tree
Showing 11 changed files with 419 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
config.json
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# cards-generator

Generate cards for bot

[![Go Report Card](https://goreportcard.com/badge/github.com/train-cat/cards-generator)](https://goreportcard.com/report/github.com/train-cat/cards-generator)

## Exemple
<img src="example.png" />
57 changes: 57 additions & 0 deletions cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package main

import (
"image"

"github.com/fogleman/gg"
log "github.com/sirupsen/logrus"
)

var cacheImages = map[int]image.Image{}

func getBaseImage(week Days) image.Image {
img, ok := cacheImages[int(week)]

if !ok || refreshCache {
img = generateBaseImage(week)

log.Infof("miss cache")

cacheImages[int(week)] = img
}

return img
}

func generateBaseImage(week Days) image.Image {
dc := gg.NewContext(width, height)

dc.SetColor(backgroundColor)
dc.Clear()

drawDays(dc, week)

return dc.Image()
}

func drawDays(dc *gg.Context, week Days) {
for _, d := range days {
if week.HasFlag(d.Flag) {
loadDayOn(dc)
} else {
loadDayOff(dc)
}

dc.DrawStringAnchored(d.Letter, float64(d.PosX), float64(centerCaseDays), 0.5, 0.5)
}
}

func loadDayOn(dc *gg.Context) {
dc.SetFontFace(fontBold)
dc.SetColor(colorDayOn)
}

func loadDayOff(dc *gg.Context) {
dc.SetFontFace(fontRegular)
dc.SetColor(colorDayOff)
}
75 changes: 75 additions & 0 deletions config.json.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"font": {
"regular": {
"size": 24,
"path": "fonts/Roboto-Regular.ttf"
},
"bold": {
"size": 32,
"path": "fonts/Roboto-Bold.ttf"
}
},
"text": {
"limit": 24,
"cut_after": 22
},
"image": {
"color": {
"background": {
"R": 0,
"G": 136,
"B": 208,
"A": 255
},
"day_on": {
"R": 249,
"G": 186,
"B": 24,
"A": 255
},
"day_off": {
"R": 230,
"G": 230,
"B": 230,
"A": 255
},
"text": {
"R": 255,
"G": 255,
"B": 255,
"A": 255
}
},
"size": {
"height": 200,
"width": 382
},
"position": {
"days": {
"y": 150
},
"mission": {
"x": 362,
"y": 10
},
"schedule": {
"x": 15,
"y": 10
},
"origin": {
"x": 15,
"y": 60
},
"terminus": {
"x": 15,
"y": 95
}
}
},
"cache": {
"force_refresh": false
},
"http": {
"port": 9090
}
}
38 changes: 38 additions & 0 deletions days.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package main

const (
Sunday = 1 << iota
Saturday
Friday
Thursday
Wednesday
Tuesday
Monday

daysPerWeek = 7
)

type (
// Days is binary representation
Days uint8

Day struct {
Flag Days
Letter string
PosX int
}
)

var days []Day

// HasFlag return true if mask has specific flag set
func (d Days) HasFlag(flag Days) bool { return d&flag != 0 }

// AddFlag to the binary representation
func (d *Days) AddFlag(flag Days) { *d |= flag }

// ClearFlag remove flag
func (d *Days) ClearFlag(flag Days) { *d &= ^flag }

// ToggleFlag inverse state of the flag
func (d *Days) ToggleFlag(flag Days) { *d ^= flag }
Binary file added example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added fonts/Roboto-Bold.ttf
Binary file not shown.
Binary file added fonts/Roboto-Regular.ttf
Binary file not shown.
47 changes: 47 additions & 0 deletions generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package main

import (
"fmt"
"net/http"
"strconv"

"github.com/fogleman/gg"
)

func serveImage(w http.ResponseWriter, r *http.Request) {
v := r.URL.Query()

mission := v.Get("mission")
origin := formatStation(v.Get("origin"))
terminus := formatStation(v.Get("terminus"))
schedule := v.Get("schedule")
days, err := strconv.Atoi(v.Get("days"))

if mission == "" || origin == "" || terminus == "" || schedule == "" || days == 0 || days > 127 || err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("{\"status\": \"bad request\"}"))
return
}

dc := gg.NewContextForImage(getBaseImage(Days(days)))

dc.SetColor(colorText)

dc.SetFontFace(fontRegular)
dc.DrawStringAnchored(mission, xMission, yMission, 1, 1)
dc.DrawStringAnchored(schedule, xSchedule, ySchedule, 0, 1)

dc.SetFontFace(fontBold)
dc.DrawStringAnchored(origin, xOrigin, yOrigin, 0, 1)
dc.DrawStringAnchored(terminus, xTerminus, yTerminus, 0, 1)

dc.EncodePNG(w)
}

func formatStation(name string) string {
if len(name) > limit {
return fmt.Sprintf("%s...", name[:cutAfter])
}

return name
}
141 changes: 141 additions & 0 deletions init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package main

import (
"flag"
"image/color"

"github.com/fogleman/gg"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
"golang.org/x/image/font"
)

var (
refreshCache bool
limit int
cutAfter int

fontRegular font.Face
fontBold font.Face

height int
width int
heightDays int
widthPerCase int
heightPerCase int
centerCaseDays int

backgroundColor color.Color
colorDayOn color.Color
colorDayOff color.Color
colorText color.Color

xMission float64
yMission float64
xSchedule float64
ySchedule float64
xOrigin float64
yOrigin float64
xTerminus float64
yTerminus float64
)

func init() {
initConfig()
initFont()
initVar()
initDays()
}

func initConfig() {
cfgFile := flag.String("config", "config.json", "config file")
flag.Parse()

viper.SetConfigFile(*cfgFile)
viper.AutomaticEnv() // read in environment variables that match

// If a config file is found, read it in.
if err := viper.ReadInConfig(); err != nil {
log.Fatal(err)
}
}

func initFont() {
var err error

fontRegular, err = gg.LoadFontFace(viper.GetString("font.regular.path"), viper.GetFloat64("font.regular.size"))
if err != nil {
log.Fatal(err)
}

fontBold, err = gg.LoadFontFace(viper.GetString("font.bold.path"), viper.GetFloat64("font.bold.size"))
if err != nil {
log.Fatal(err)
}
}

func initVar() {
// size
height = viper.GetInt("image.size.height")
width = viper.GetInt("image.size.width")
heightDays = viper.GetInt("image.position.days.y")
widthPerCase = width / daysPerWeek
heightPerCase = height - heightDays
centerCaseDays = height - heightPerCase/2

// color
backgroundColor = color.RGBA{
R: uint8(viper.GetInt("image.color.background.R")),
G: uint8(viper.GetInt("image.color.background.G")),
B: uint8(viper.GetInt("image.color.background.B")),
A: uint8(viper.GetInt("image.color.background.A")),
}
colorDayOn = color.RGBA{
R: uint8(viper.GetInt("image.color.day_on.R")),
G: uint8(viper.GetInt("image.color.day_on.G")),
B: uint8(viper.GetInt("image.color.day_on.B")),
A: uint8(viper.GetInt("image.color.day_on.A")),
}
colorDayOff = color.RGBA{
R: uint8(viper.GetInt("image.color.day_off.R")),
G: uint8(viper.GetInt("image.color.day_off.G")),
B: uint8(viper.GetInt("image.color.day_off.B")),
A: uint8(viper.GetInt("image.color.day_off.A")),
}
colorText = color.RGBA{
R: uint8(viper.GetInt("image.color.text.R")),
G: uint8(viper.GetInt("image.color.text.G")),
B: uint8(viper.GetInt("image.color.text.B")),
A: uint8(viper.GetInt("image.color.text.A")),
}

// config
refreshCache = viper.GetBool("cache.force_refresh")
limit = viper.GetInt("text.limit")
cutAfter = viper.GetInt("text.cut_after")

// position
xMission = viper.GetFloat64("image.position.mission.x")
yMission = viper.GetFloat64("image.position.mission.y")

xSchedule = viper.GetFloat64("image.position.schedule.x")
ySchedule = viper.GetFloat64("image.position.schedule.y")

xOrigin = viper.GetFloat64("image.position.origin.x")
yOrigin = viper.GetFloat64("image.position.origin.y")

xTerminus = viper.GetFloat64("image.position.terminus.x")
yTerminus = viper.GetFloat64("image.position.terminus.y")
}

func initDays() {
days = []Day{
{Monday, "L", widthPerCase / 2},
{Tuesday, "M", widthPerCase*1 + widthPerCase/2},
{Wednesday, "M", widthPerCase*2 + widthPerCase/2},
{Thursday, "J", widthPerCase*3 + widthPerCase/2},
{Friday, "V", widthPerCase*4 + widthPerCase/2},
{Saturday, "S", widthPerCase*5 + widthPerCase/2},
{Sunday, "D", widthPerCase*6 + widthPerCase/2},
}
}
Loading

0 comments on commit e829090

Please sign in to comment.