You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

152 lines
3.5 KiB

package main
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"strconv"
"time"
"github.com/fatih/color"
)
type Project struct {
Name string `json:"name"`
Streaks []Streak `json:"streaks"`
}
type Streak struct {
Start time.Time `json:"start"`
End time.Time `json:"end"`
Duration time.Duration `json:"duration"`
Description string `json:"description"`
}
type Work struct {
Projects []Project `json:"projects"`
CurrentProjectName string `json:"currentProjectName"`
}
var work Work
func readProjects() {
file, err := ioutil.ReadFile(filePath)
if err != nil {
//file not exists, create directory and file
color.Yellow(directoryPath + " not exists, creating directory")
_ = os.Mkdir(directoryPath, os.ModePerm)
saveWork()
}
content := string(file)
json.Unmarshal([]byte(content), &work)
}
func saveWork() {
jsonProjects, err := json.Marshal(work)
check(err)
err = ioutil.WriteFile(filePath, jsonProjects, 0644)
check(err)
}
func getProjectIByName(name string) int {
for i, project := range work.Projects {
if project.Name == name {
return i
}
}
return -1
}
func projectExist(name string) bool {
for _, project := range work.Projects {
if project.Name == name {
return true
}
}
return false
}
func newProject(name string) error {
//first, check if the project name is not taken yet
if projectExist(name) {
color.Red("Project name: " + name + ", already exists")
return errors.New("project name already exist")
}
var newProject Project
newProject.Name = name
work.Projects = append(work.Projects, newProject)
return nil
}
func listProjectsDetails() {
fmt.Println("")
fmt.Println("")
fmt.Println("Listing projects")
fmt.Println("")
for k, project := range work.Projects {
fmt.Println("project " + strconv.Itoa(k))
fmt.Print("name: ")
color.Blue(project.Name)
for k2, streak := range project.Streaks {
fmt.Println(" streak: " + strconv.Itoa(k2))
fmt.Print(" Start:")
fmt.Println(streak.Start)
fmt.Print(" End:")
fmt.Println(streak.End)
fmt.Print(" Duration:")
fmt.Println(streak.Duration)
}
fmt.Println("")
showHoursByDays(project.Name)
fmt.Println("")
}
if work.CurrentProjectName != "" {
fmt.Print("Current working project: ")
color.Blue(work.CurrentProjectName)
}
}
func listProjects() {
fmt.Println("")
fmt.Println("")
fmt.Println("Listing projects")
fmt.Println("")
for k, project := range work.Projects {
fmt.Println("project " + strconv.Itoa(k))
fmt.Print("name: ")
color.Blue(project.Name)
showHoursByDays(project.Name)
fmt.Println("")
}
if work.CurrentProjectName != "" {
fmt.Print("Current working project: ")
color.Blue(work.CurrentProjectName)
}
}
func deleteProject(name string) {
i := getProjectIByName(name)
if i < 0 {
color.Red("Project name: " + name + ", no exists")
return
}
work.Projects = append(work.Projects[:i], work.Projects[i+1:]...)
}
func showHoursByDays(name string) {
timeFormat := "Mon, 01/02/06"
i := getProjectIByName(name)
if i < 0 {
color.Red("Project name: " + name + ", no exists")
return
}
p := work.Projects[i]
days := make(map[string]time.Duration)
for _, streak := range p.Streaks {
days[streak.Start.Format(timeFormat)] = addDurations(days[streak.Start.Format(timeFormat)], streak.Duration)
}
for day, hours := range days {
fmt.Print(" Day: " + day)
fmt.Print(", total time: ")
fmt.Println(hours)
}
}
func addDurations(d1 time.Duration, d2 time.Duration) time.Duration {
s := d1.Seconds() + d2.Seconds()
r := time.Duration(s) * time.Second
return r
}