2015-01-27 16:00:05 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
"fmt"
|
|
|
|
"time"
|
2015-01-27 21:16:32 +00:00
|
|
|
"flag"
|
2015-01-27 16:00:05 +00:00
|
|
|
"sort"
|
|
|
|
"bufio"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"text/template"
|
|
|
|
)
|
|
|
|
|
2015-01-27 21:16:32 +00:00
|
|
|
const scores = "/home/krowbar/Code/irc/tildescores.txt"
|
|
|
|
|
2015-01-27 16:00:05 +00:00
|
|
|
func main() {
|
|
|
|
fmt.Println("Starting...")
|
|
|
|
|
2015-01-27 21:16:32 +00:00
|
|
|
// Get any arguments
|
|
|
|
outPtr := flag.String("o", "tildescores", "Output file name")
|
|
|
|
flag.Parse()
|
|
|
|
|
2015-01-27 16:00:05 +00:00
|
|
|
headers := []string{ "User", "Tildes", "Last Collection" }
|
2015-01-27 21:16:32 +00:00
|
|
|
generate("tilde collectors", sortScore(readData(scores, "&^%", headers)), *outPtr)
|
2015-01-27 16:00:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Table struct {
|
|
|
|
Headers []string
|
|
|
|
Rows []Row
|
|
|
|
}
|
|
|
|
|
|
|
|
type Row struct {
|
|
|
|
Data []string
|
|
|
|
}
|
|
|
|
|
|
|
|
type By func(r1, r2 *Row) bool
|
|
|
|
func (by By) Sort(rows []Row) {
|
|
|
|
rs := &rowSorter {
|
|
|
|
rows: rows,
|
|
|
|
by: by,
|
|
|
|
}
|
|
|
|
sort.Sort(rs)
|
|
|
|
}
|
|
|
|
type rowSorter struct {
|
|
|
|
rows []Row
|
|
|
|
by func(r1, r2 *Row) bool
|
|
|
|
}
|
|
|
|
func (r *rowSorter) Len() int {
|
|
|
|
return len(r.rows)
|
|
|
|
}
|
|
|
|
func (r *rowSorter) Swap(i, j int) {
|
|
|
|
r.rows[i], r.rows[j] = r.rows[j], r.rows[i]
|
|
|
|
}
|
|
|
|
func (r *rowSorter) Less(i, j int) bool {
|
|
|
|
return r.by(&r.rows[i], &r.rows[j])
|
|
|
|
}
|
|
|
|
|
|
|
|
func sortScore(table *Table) *Table {
|
|
|
|
score := func(r1, r2 *Row) bool {
|
|
|
|
s1, _ := strconv.Atoi(r1.Data[1])
|
|
|
|
s2, _ := strconv.Atoi(r2.Data[1])
|
|
|
|
return s1 < s2
|
|
|
|
}
|
|
|
|
decScore := func(r1, r2 *Row) bool {
|
|
|
|
return !score(r1, r2)
|
|
|
|
}
|
|
|
|
By(decScore).Sort(table.Rows)
|
|
|
|
|
|
|
|
return table
|
|
|
|
}
|
|
|
|
|
2015-01-27 21:17:46 +00:00
|
|
|
func parseTimestamp(ts string) time.Time {
|
|
|
|
t, err := strconv.ParseInt(ts, 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return time.Unix(t, 0)
|
|
|
|
}
|
|
|
|
|
2015-01-27 16:00:05 +00:00
|
|
|
func readData(path string, delimiter string, headers []string) *Table {
|
|
|
|
f, _ := os.Open(path)
|
|
|
|
|
|
|
|
defer f.Close()
|
|
|
|
|
|
|
|
rows := []Row{}
|
|
|
|
table := &Table{Headers: headers, Rows: nil}
|
|
|
|
s := bufio.NewScanner(f)
|
|
|
|
s.Split(bufio.ScanLines)
|
|
|
|
|
2015-01-27 21:17:46 +00:00
|
|
|
const layout = "Jan 2, 2006 3:04pm MST"
|
2015-01-27 16:00:05 +00:00
|
|
|
for s.Scan() {
|
|
|
|
data := strings.Split(s.Text(), delimiter)
|
2015-01-27 21:17:46 +00:00
|
|
|
t := parseTimestamp(data[2])
|
|
|
|
data[2] = t.UTC().Format(layout)
|
2015-01-27 16:00:05 +00:00
|
|
|
row := &Row{Data: data}
|
|
|
|
rows = append(rows, *row)
|
|
|
|
}
|
|
|
|
table.Rows = rows
|
|
|
|
|
|
|
|
return table
|
|
|
|
}
|
|
|
|
|
|
|
|
type Page struct {
|
|
|
|
Title string
|
|
|
|
Table Table
|
|
|
|
Updated string
|
|
|
|
UpdatedForHumans string
|
|
|
|
}
|
|
|
|
|
2015-01-27 21:18:16 +00:00
|
|
|
func add(x, y int) int {
|
|
|
|
return x + y
|
|
|
|
}
|
|
|
|
|
2015-01-27 16:00:05 +00:00
|
|
|
func generate(title string, table *Table, outputFile string) {
|
|
|
|
fmt.Println("Generating page.")
|
|
|
|
|
|
|
|
f, err := os.Create(os.Getenv("HOME") + "/public_html/" + outputFile + ".html")
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
defer f.Close()
|
|
|
|
|
2015-01-27 21:18:16 +00:00
|
|
|
funcMap := template.FuncMap {
|
|
|
|
"add": add,
|
|
|
|
}
|
|
|
|
|
2015-01-27 16:00:05 +00:00
|
|
|
w := bufio.NewWriter(f)
|
2015-01-27 21:18:16 +00:00
|
|
|
template, err := template.New("").Funcs(funcMap).ParseFiles("templates/table.html")
|
2015-01-27 16:00:05 +00:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extra page data
|
|
|
|
curTime := time.Now().UTC()
|
|
|
|
updatedReadable := curTime.Format(time.RFC1123)
|
|
|
|
updated := curTime.Format(time.RFC3339)
|
|
|
|
|
|
|
|
// Generate the page
|
|
|
|
page := &Page{Title: title, Table: *table, UpdatedForHumans: updatedReadable, Updated: updated}
|
|
|
|
template.ExecuteTemplate(w, "table", page)
|
|
|
|
w.Flush()
|
|
|
|
|
|
|
|
fmt.Println("DONE!")
|
|
|
|
}
|