diff --git a/assets/colorscales/green-blue-9.csv b/assets/colorscales/green-blue-9.csv new file mode 100644 index 0000000..a61404e --- /dev/null +++ b/assets/colorscales/green-blue-9.csv @@ -0,0 +1,10 @@ +R,G,B +247,252,240 +224,243,219 +204,235,197 +168,221,181 +123,204,196 +78,179,211 +43,140,190 +8,104,172 +8,64,129 \ No newline at end of file diff --git a/assets/fonts/Sunflower-Medium.ttf b/assets/fonts/Sunflower-Medium.ttf new file mode 100644 index 0000000..9e44fe7 Binary files /dev/null and b/assets/fonts/Sunflower-Medium.ttf differ diff --git a/daily-headmap.go b/daily-headmap.go new file mode 100644 index 0000000..0e72dba --- /dev/null +++ b/daily-headmap.go @@ -0,0 +1,116 @@ +package main + +import ( + "bytes" + _ "embed" + "encoding/json" + "fmt" + "github.com/nikolaydubina/calendarheatmap/charts" + "github.com/urfave/cli/v2" + "golang.org/x/image/font" + "golang.org/x/image/font/opentype" + "image/color" + "os" + "strings" + "time" + + _ "github.com/nikolaydubina/calendarheatmap/charts" + _ "golang.org/x/image/font" + _ "golang.org/x/image/font/opentype" +) + +//go:embed assets/fonts/Sunflower-Medium.ttf +var defaultFontFaceBytes []byte + +//go:embed assets/colorscales/green-blue-9.csv +var defaultColorScaleBytes []byte + +func dailyHabitImage(cCtx *cli.Context) error { + folder := DATAPATH + files, err := os.ReadDir(folder) + if err != nil { + return err + } + + counts := make(map[string]int) + + for _, f := range files { + if f.IsDir() { + continue + } + + day := strings.TrimSuffix(f.Name(), ".json") + + content, err := os.ReadFile(fmt.Sprintf("%v/%v", folder, f.Name())) + if err != nil { + return err + } + + var data []archivCard + err = json.Unmarshal(content, &data) + if err != nil { + return err + } + + inToDo := 0 + all := 0 + + for _, archivCard := range data { + if archivCard.List == "ToDo" { + inToDo++ + } + all++ + } + + var percent float64 + percent = float64(all-inToDo) / float64(all) * 100 + + counts[day] = int(percent) + } + + colorscale, err := charts.NewBasicColorscaleFromCSV(bytes.NewBuffer(defaultColorScaleBytes)) + if err != nil { + return err + } + + fontFace, err := charts.LoadFontFace(defaultFontFaceBytes, opentype.FaceOptions{ + Size: 26, + DPI: 280, + Hinting: font.HintingNone, + }) + if err != nil { + return err + } + + conf := charts.HeatmapConfig{ + Counts: counts, + ColorScale: colorscale, + DrawMonthSeparator: false, + DrawLabels: true, + Margin: 30, + BoxSize: 150, + MonthSeparatorWidth: 5, + MonthLabelYOffset: 50, + TextWidthLeft: 300, + TextHeightTop: 200, + TextColor: color.RGBA{100, 100, 100, 255}, + BorderColor: color.RGBA{200, 200, 200, 255}, + Locale: "en_US", + Format: "png", + FontFace: fontFace, + ShowWeekdays: map[time.Weekday]bool{ + time.Monday: true, + time.Wednesday: true, + time.Friday: true, + }, + } + + f, err := os.OpenFile("headmap.png", os.O_WRONLY|os.O_CREATE, 0644) + defer f.Close() + err = charts.WriteHeatmap(conf, f) + if err != nil { + return err + } + + return nil +} diff --git a/go.mod b/go.mod index a6b7e42..e0ca4e0 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,10 @@ go 1.22.0 require ( github.com/adlio/trello v1.10.0 + github.com/nikolaydubina/calendarheatmap v1.7.0 github.com/rs/zerolog v1.32.0 github.com/urfave/cli/v2 v2.27.1 + golang.org/x/image v0.15.0 ) require ( @@ -16,5 +18,6 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect golang.org/x/sys v0.12.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect ) diff --git a/go.sum b/go.sum index 31999e2..0c53913 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/nikolaydubina/calendarheatmap v1.7.0 h1:NRzVfydhxRYMzcj3SYAy31y+yi1DCCzcD0YxDy57Nco= +github.com/nikolaydubina/calendarheatmap v1.7.0/go.mod h1:PIfHapXuizDttmpJsATJA1snrjibFQdIAbmm5Xh3SrQ= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -21,9 +23,15 @@ github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho= github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= +golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/main.go b/main.go index a754997..94403bb 100644 --- a/main.go +++ b/main.go @@ -43,6 +43,11 @@ func main() { Usage: "Assign all cards without member to current users", Action: unassignCards, }, + { + Name: "daily-habit-image", + Usage: "Daily habit image", + Action: dailyHabitImage, + }, }, } diff --git a/reset-daily-tasks.go b/reset-daily-tasks.go index afc9395..1ca98b2 100644 --- a/reset-daily-tasks.go +++ b/reset-daily-tasks.go @@ -1,13 +1,23 @@ package main import ( + "encoding/json" "errors" "fmt" "github.com/adlio/trello" "github.com/rs/zerolog/log" "github.com/urfave/cli/v2" + "os" + "time" ) +type archivCard struct { + Name string + List string +} + +const DATAPATH = "/home/pi/dailyhabbit" + func resetDailyTasks(cCtx *cli.Context) error { client := getTrelloClient() board, err := client.GetBoard(trelloBordID, trello.Defaults()) @@ -48,10 +58,12 @@ func resetDailyTasks(cCtx *cli.Context) error { var todoList *trello.List + listnames := make(map[string]string) + for _, list := range lists { + listnames[list.ID] = list.Name if list.Name == "ToDo" { todoList = list - break } } @@ -67,6 +79,8 @@ func resetDailyTasks(cCtx *cli.Context) error { log.Debug().Int("number of cards", len(cards)).Msg("Get Cards") + var dailyCards []archivCard + for _, card := range cards { log.Debug().Str("name", card.Name).Msg("Check") foundLabel := false @@ -83,11 +97,29 @@ func resetDailyTasks(cCtx *cli.Context) error { continue } + cd := archivCard{ + Name: card.Name, + List: listnames[card.IDList], + } + dailyCards = append(dailyCards, cd) + err = card.MoveToList(todoList.ID, trello.Defaults()) if err != nil { return fmt.Errorf("cant move card to todo list: %w", err) } } + data, err := json.Marshal(dailyCards) + if err != nil { + return fmt.Errorf("cant marshal data for archiov: %w", err) + } + + err = os.WriteFile(fmt.Sprintf("%v/%v.json", DATAPATH, time.Now().Format(time.DateOnly)), data, 0744) + if err != nil { + return fmt.Errorf("cant wrote daily habbit file: %w", err) + } + + fmt.Println(string(data)) + return nil }