sync: Extract function that import hints from importer

This commit is contained in:
nemunaire 2019-07-06 00:40:31 +02:00
parent 4039a394b5
commit eb95d861d3
1 changed files with 75 additions and 55 deletions

View File

@ -15,72 +15,92 @@ import (
_ "golang.org/x/crypto/blake2b"
)
// SyncExerciceHints reads the content of hints/ directories and import it as EHint for the given challenge.
func SyncExerciceHints(i Importer, exercice fic.Exercice) (errs []string) {
func buildExerciceHints(i Importer, exercice fic.Exercice) (hints []fic.EHint, errs []string) {
params, err := parseExerciceParams(i, exercice.Path)
if err != nil {
errs = append(errs, fmt.Sprintf("%q: challenge.txt: %s", path.Base(exercice.Path), err))
return
}
for n, hint := range params.Hints {
h := fic.EHint{}
if hint.Title == "" {
h.Title = fmt.Sprintf("Astuce #%d", n+1)
} else {
h.Title = fixnbsp(hint.Title)
}
if hint.Cost <= 0 {
h.Cost = exercice.Gain / 4
} else {
h.Cost = hint.Cost
}
if hint.Filename != "" {
if hint.Content != "" {
errs = append(errs, fmt.Sprintf("%q: challenge.txt: hint %s (%d): content and filename can't be filled at the same time", path.Base(exercice.Path), hint.Title, n+1))
continue
} else if !i.exists(path.Join(exercice.Path, "hints", hint.Filename)) {
errs = append(errs, fmt.Sprintf("%q: challenge.txt: hint %s (%d): %s: File not found", path.Base(exercice.Path), hint.Title, n+1, hint.Filename))
continue
} else {
// Handle files as downloadable content
if res, err := i.importFile(path.Join(exercice.Path, "hints", hint.Filename), func(filePath string, origin string) (interface{}, error) {
// Calculate hash
hash512 := crypto.BLAKE2b_512.New()
if fd, err := os.Open(filePath); err != nil {
return nil, err
} else {
defer fd.Close()
reader := bufio.NewReader(fd)
if _, err := io.Copy(hash512, reader); err != nil {
return nil, err
}
}
result512 := hash512.Sum(nil)
// Special format for downloadable hints: $FILES + hexhash + path from FILES/
return "$FILES" + hex.EncodeToString(result512) + strings.TrimPrefix(filePath, fic.FilesDir), nil
}); err != nil {
errs = append(errs, fmt.Sprintf("%q: unable to import hint file %q: %s", path.Base(exercice.Path), hint.Filename, err))
continue
} else if s, ok := res.(string); !ok {
errs = append(errs, fmt.Sprintf("%q: unable to import hint file %q: invalid string returned as filename", path.Base(exercice.Path), hint.Filename))
continue
} else {
h.Content = s
}
}
} else if hint.Content == "" {
errs = append(errs, fmt.Sprintf("%q: challenge.txt: hint %s (%d): content and filename can't be empty at the same time", path.Base(exercice.Path), hint.Title, n+1))
continue
} else if h.Content, err = ProcessMarkdown(i, fixnbsp(hint.Content), exercice.Path); err != nil {
errs = append(errs, fmt.Sprintf("%q: challenge.txt: hint %s (%d): error during markdown formating: %s", path.Base(exercice.Path), hint.Title, n+1, err))
}
hints = append(hints, h)
}
return
}
// CheckExerciceHints checks if all hints are corrects..
func CheckExerciceHints(i Importer, exercice fic.Exercice) ([]fic.EHint, []string) {
return buildExerciceHints(i, exercice)
}
// SyncExerciceHints reads the content of hints/ directories and import it as EHint for the given challenge.
func SyncExerciceHints(i Importer, exercice fic.Exercice) (errs []string) {
if _, err := exercice.WipeHints(); err != nil {
errs = append(errs, err.Error())
} else {
for n, hint := range params.Hints {
if hint.Title == "" {
hint.Title = fmt.Sprintf("Astuce #%d", n+1)
} else {
hint.Title = fixnbsp(hint.Title)
}
if hint.Cost <= 0 {
hint.Cost = exercice.Gain / 4
}
if hint.Filename != "" {
if hint.Content != "" {
errs = append(errs, fmt.Sprintf("%q: challenge.txt: hint %s (%d): content and filename can't be filled at the same time", path.Base(exercice.Path), hint.Title, n+1))
continue
} else if !i.exists(path.Join(exercice.Path, "hints", hint.Filename)) {
errs = append(errs, fmt.Sprintf("%q: challenge.txt: hint %s (%d): %s: File not found", path.Base(exercice.Path), hint.Title, n+1, hint.Filename))
continue
} else {
// Handle files as downloadable content
if res, err := i.importFile(path.Join(exercice.Path, "hints", hint.Filename), func(filePath string, origin string) (interface{}, error) {
// Calculate hash
hash512 := crypto.BLAKE2b_512.New()
if fd, err := os.Open(filePath); err != nil {
return nil, err
} else {
defer fd.Close()
reader := bufio.NewReader(fd)
if _, err := io.Copy(hash512, reader); err != nil {
return nil, err
}
}
result512 := hash512.Sum(nil)
// Special format for downloadable hints: $FILES + hexhash + path from FILES/
return "$FILES" + hex.EncodeToString(result512) + strings.TrimPrefix(filePath, fic.FilesDir), nil
}); err != nil {
errs = append(errs, fmt.Sprintf("%q: unable to import hint file %q: %s", path.Base(exercice.Path), hint.Filename, err))
continue
} else if s, ok := res.(string); !ok {
errs = append(errs, fmt.Sprintf("%q: unable to import hint file %q: invalid string returned as filename", path.Base(exercice.Path), hint.Filename))
continue
} else {
hint.Content = s
}
}
} else if hint.Content == "" {
errs = append(errs, fmt.Sprintf("%q: challenge.txt: hint %s (%d): content and filename can't be empty at the same time", path.Base(exercice.Path), hint.Title, n+1))
continue
} else if hint.Content, err = ProcessMarkdown(i, fixnbsp(hint.Content), exercice.Path); err != nil{
errs = append(errs, fmt.Sprintf("%q: challenge.txt: hint %s (%d): error during markdown formating: %s", path.Base(exercice.Path), hint.Title, n+1, err))
}
hints, berrs := buildExerciceHints(i, exercice)
errs = append(errs, berrs...)
for n, hint := range hints {
// Import hint
if _, err := exercice.AddHint(hint.Title, hint.Content, hint.Cost); err != nil {
errs = append(errs, fmt.Sprintf("%q: challenge.txt: hint %s (%d): %s", path.Base(exercice.Path), hint.Title, n+1, err))
errs = append(errs, fmt.Sprintf("%q: hint #%d %s: %s", path.Base(exercice.Path), n+1, hint.Title, err))
}
}
}