2019-09-02 19:47:24 -06:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2020-02-22 15:49:58 -07:00
|
|
|
"github.com/spf13/afero"
|
2020-02-29 22:37:22 -07:00
|
|
|
"log"
|
2019-11-24 15:58:43 -07:00
|
|
|
"strings"
|
2020-03-01 13:27:49 -07:00
|
|
|
"bufio"
|
|
|
|
"strconv"
|
2020-03-01 14:03:46 -07:00
|
|
|
"time"
|
|
|
|
"fmt"
|
2019-09-02 19:47:24 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
type Mothballs struct {
|
|
|
|
categories map[string]*Zipfs
|
2020-02-29 16:51:32 -07:00
|
|
|
afero.Fs
|
2019-09-02 19:47:24 -06:00
|
|
|
}
|
|
|
|
|
2020-02-22 15:49:58 -07:00
|
|
|
func NewMothballs(fs afero.Fs) *Mothballs {
|
2019-09-02 19:47:24 -06:00
|
|
|
return &Mothballs{
|
2020-02-29 22:37:22 -07:00
|
|
|
Fs: fs,
|
2019-09-02 19:47:24 -06:00
|
|
|
categories: make(map[string]*Zipfs),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-01 16:10:55 -07:00
|
|
|
func (m *Mothballs) Open(cat string, points int, filename string) (ReadSeekCloser, time.Time, error) {
|
2020-03-01 14:03:46 -07:00
|
|
|
mb, ok := m.categories[cat]
|
|
|
|
if ! ok {
|
2020-03-01 16:10:55 -07:00
|
|
|
return nil, time.Time{}, fmt.Errorf("No such category: %s", cat)
|
2020-03-01 14:03:46 -07:00
|
|
|
}
|
|
|
|
|
2020-03-01 16:10:55 -07:00
|
|
|
f, err := mb.Open(fmt.Sprintf("content/%d/%s", points, filename))
|
|
|
|
return f, mb.ModTime(), err
|
2020-02-29 16:51:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Mothballs) Inventory() []Category {
|
2020-03-01 13:27:49 -07:00
|
|
|
categories := make([]Category, 0, 20)
|
2020-03-01 12:44:21 -07:00
|
|
|
for cat, zfs := range m.categories {
|
2020-03-01 13:27:49 -07:00
|
|
|
pointsList := make([]int, 0, 20)
|
|
|
|
pf, err := zfs.Open("puzzles.txt")
|
|
|
|
if err != nil {
|
|
|
|
// No puzzles = no category
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
scanner := bufio.NewScanner(pf)
|
|
|
|
for scanner.Scan() {
|
|
|
|
line := scanner.Text()
|
|
|
|
if pointval, err := strconv.Atoi(line); err != nil {
|
|
|
|
log.Printf("Reading points for %s: %s", cat, err.Error())
|
|
|
|
} else {
|
|
|
|
pointsList = append(pointsList, pointval)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
categories = append(categories, Category{cat, pointsList})
|
2020-03-01 12:44:21 -07:00
|
|
|
}
|
2020-03-01 13:27:49 -07:00
|
|
|
return categories
|
2020-02-29 16:51:32 -07:00
|
|
|
}
|
|
|
|
|
2020-03-01 16:10:55 -07:00
|
|
|
func (m *Mothballs) CheckAnswer(cat string, points int, answer string) error {
|
|
|
|
zfs, ok := m.categories[cat]
|
|
|
|
if ! ok {
|
|
|
|
return fmt.Errorf("No such category: %s", cat)
|
|
|
|
}
|
|
|
|
|
|
|
|
af, err := zfs.Open("answers.txt")
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("No answers.txt file")
|
|
|
|
}
|
|
|
|
defer af.Close()
|
|
|
|
|
|
|
|
needle := fmt.Sprintf("%d %s", points, answer)
|
|
|
|
scanner := bufio.NewScanner(af)
|
|
|
|
for scanner.Scan() {
|
|
|
|
if scanner.Text() == needle {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmt.Errorf("Invalid answer")
|
|
|
|
}
|
|
|
|
|
2020-02-29 16:51:32 -07:00
|
|
|
func (m *Mothballs) Update() {
|
2019-09-02 19:47:24 -06:00
|
|
|
// Any new categories?
|
2020-02-29 16:51:32 -07:00
|
|
|
files, err := afero.ReadDir(m.Fs, "/")
|
2019-09-02 19:47:24 -06:00
|
|
|
if err != nil {
|
|
|
|
log.Print("Error listing mothballs: ", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for _, f := range files {
|
|
|
|
filename := f.Name()
|
|
|
|
if !strings.HasSuffix(filename, ".mb") {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
categoryName := strings.TrimSuffix(filename, ".mb")
|
|
|
|
|
|
|
|
if _, ok := m.categories[categoryName]; !ok {
|
2020-02-29 16:51:32 -07:00
|
|
|
zfs, err := OpenZipfs(m.Fs, filename)
|
2019-09-02 19:47:24 -06:00
|
|
|
if err != nil {
|
2020-02-29 16:51:32 -07:00
|
|
|
log.Print("Error opening ", filename, ": ", err)
|
2019-09-02 19:47:24 -06:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
log.Print("New mothball: ", filename)
|
|
|
|
m.categories[categoryName] = zfs
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|