wrappd.sh/internal/web/utils.go
Óscar M. Lage f7cf197b4e Imp: The file does not need to be copied in disk anymore
File is being proccessed from memory directly. We don't need to
tempcopy nor delete it because it's not saved to disk.
2024-12-05 16:43:51 +01:00

163 lines
3.4 KiB
Go

package web
import (
"bufio"
"encoding/json"
"fmt"
"html/template"
"log"
"net/http"
"os"
"path/filepath"
"sort"
"strings"
"github.com/go-echarts/go-echarts/v2/charts"
"github.com/go-echarts/go-echarts/v2/opts"
)
func loadTemplates(name string) (*template.Template, error) {
funcs := template.FuncMap{
"safeHTML": func(s string) interface{} { return template.HTML(s) },
}
templates, err := loadTemplatesFromDir("internal/web/templates")
if err != nil {
log.Printf("Error loading templates: %v", err)
return nil, err
}
return template.New(name).Funcs(funcs).ParseFiles(templates...)
}
func ConvertAndSort[K comparable](data map[K]int, limit int) []CommandStat {
var result []CommandStat
for key, count := range data {
result = append(result, CommandStat{
Command: fmt.Sprintf("%v", key),
Count: count,
})
}
sort.Slice(result, func(i, j int) bool {
return result[i].Count > result[j].Count
})
if len(result) > limit {
result = result[:limit]
}
return result
}
func parseHistoryFile(file http.File) (map[string]int, error) {
commandCounts := make(map[string]int)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
command := strings.Fields(line)[0]
commandCounts[command]++
}
if err := scanner.Err(); err != nil {
return nil, err
}
return commandCounts, nil
}
func generateTopCommands(commandCounts map[string]int, topN int) []CommandStat {
stats := make([]CommandStat, 0, len(commandCounts))
for cmd, count := range commandCounts {
stats = append(stats, CommandStat{Command: cmd, Count: count})
}
sort.Slice(stats, func(i, j int) bool {
return stats[i].Count > stats[j].Count
})
if topN < len(stats) {
stats = stats[:topN]
}
return stats
}
func createBarChart(stats []CommandStat) *charts.Bar {
bar := charts.NewBar()
bar.SetGlobalOptions(
charts.WithTitleOpts(opts.Title{
Title: "Top Commands",
Subtitle: "Most used commands",
}),
)
commands := make([]string, len(stats))
counts := make([]int, len(stats))
for i, stat := range stats {
commands[i] = stat.Command
counts[i] = stat.Count
}
bar.SetXAxis(commands).
AddSeries("Freq", generateBarItems(counts)).
SetSeriesOptions(
charts.WithLabelOpts(opts.Label{
Color: "white",
Position: "top",
}),
)
return bar
}
func generateBarItems(data []int) []opts.BarData {
items := make([]opts.BarData, len(data))
for i, v := range data {
items[i] = opts.BarData{Value: v}
}
return items
}
func saveResults(uniqueID string, stats map[string]interface{}) {
filename := "results/" + uniqueID + ".json"
file, err := os.Create(filename)
if err != nil {
log.Fatal(err)
}
defer file.Close()
json.NewEncoder(file).Encode(stats)
}
func loadResults(uniqueID string) (map[string]interface{}, error) {
filename := "results/" + uniqueID + ".json"
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
var stats map[string]interface{}
err = json.NewDecoder(file).Decode(&stats)
return stats, err
}
func loadTemplatesFromDir(dir string) ([]string, error) {
var templates []string
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && filepath.Ext(path) == ".html" {
templates = append(templates, path)
}
return nil
})
return templates, err
}