mirror of
https://github.com/fumiama/paper-manager.git
synced 2026-06-04 23:40:24 +08:00
implement GenerateFile
This commit is contained in:
@@ -236,6 +236,7 @@ func (f *FileDatabase) AddFile(lstid int, reg *Regex, istemp bool, progress func
|
||||
que := &Question{
|
||||
ID: int64(binary.LittleEndian.Uint64(m[:8])),
|
||||
FileID: file.ID,
|
||||
Major: majorq.Name,
|
||||
Plain: base14.BytesToString(sb.Bytes()),
|
||||
Images: func() []byte {
|
||||
m := make(map[string]string)
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
package global
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
"github.com/fumiama/go-docx"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidGenerateConfig = errors.New("invalid generate config")
|
||||
ErrInvalidGenerateConfig = errors.New("invalid generate config")
|
||||
ErrMajorTooLarge = errors.New("major too large")
|
||||
ErrNoEnoughQuestionToMatchRequire = errors.New("no enough question to match require")
|
||||
ErrRateLimitExceeded = errors.New("rate limit exceeded")
|
||||
)
|
||||
|
||||
// GenerateConfig 试卷生成配置
|
||||
@@ -16,9 +25,59 @@ type GenerateConfig struct {
|
||||
}
|
||||
|
||||
// GenerateFile 用一些限定条件生成新试卷, 云端不保存
|
||||
func (f *FileDatabase) GenerateFile(config *GenerateConfig) ([]byte, error) {
|
||||
if config == nil || config.Distribution == nil {
|
||||
func (f *FileDatabase) GenerateFile(config *GenerateConfig) (*docx.Docx, error) {
|
||||
if config == nil || config.Distribution == nil || len(config.Distribution) == 0 {
|
||||
return nil, ErrInvalidGenerateConfig
|
||||
}
|
||||
if len(config.Distribution) > 10 {
|
||||
return nil, ErrMajorTooLarge
|
||||
}
|
||||
docf := docx.NewA4()
|
||||
f.mu.RLock()
|
||||
defer f.mu.RUnlock()
|
||||
for n, c := range config.Distribution {
|
||||
if c == 0 {
|
||||
continue
|
||||
}
|
||||
docf.AddParagraph().AddText(string([]rune("一二三四五六七八九十")[c]) + "、" + n).Size("44").Bold()
|
||||
cond := " WHERE"
|
||||
hasfront := false
|
||||
if config.YearStart > 0 {
|
||||
cond += " Year>=" + strconv.Itoa(int(config.YearStart))
|
||||
hasfront = true
|
||||
}
|
||||
if config.YearEnd > 0 {
|
||||
if hasfront {
|
||||
cond += " AND"
|
||||
}
|
||||
cond += " Year<=" + strconv.Itoa(int(config.YearStart))
|
||||
hasfront = true
|
||||
}
|
||||
if hasfront {
|
||||
cond += " AND"
|
||||
}
|
||||
cond += " (Type&" + strconv.Itoa(int(config.TypeMask)) + ")!=0"
|
||||
ques, err := sql.QueryAll[Question](&f.db,
|
||||
"SELECT * FROM "+FileTableQuestion+
|
||||
" WHERE FileID IN (SELECT FileID FROM "+
|
||||
FileTableFile+cond+
|
||||
") ORDER BY RANDOM() limit "+strconv.Itoa(int(c))+";",
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ques) != int(c) {
|
||||
return nil, ErrNoEnoughQuestionToMatchRequire
|
||||
}
|
||||
rate := 0.0
|
||||
for _, q := range ques {
|
||||
rate += q.MaxDuplicateRate()
|
||||
}
|
||||
rate /= float64(len(ques))
|
||||
if rate > config.RateLimit {
|
||||
return nil, ErrRateLimitExceeded
|
||||
}
|
||||
// TODO: 写入question到docf
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ func (f *FileDatabase) DelQuestion(id int64, istemp bool) error {
|
||||
type Question struct {
|
||||
ID int64 // ID is the first 8 bytes of the Plain's md5
|
||||
FileID int64 // FileID is fk to File(ID)
|
||||
Major string // Major is sub's major name
|
||||
Path string // Path is the question's docx position
|
||||
Plain string // Plain is the plain text of the question (like markdown format)
|
||||
Images []byte // Images is json of the image dhash in XML, ex. ['rId1': '1234567890abcdef', ...]
|
||||
@@ -110,6 +111,21 @@ func (f *FileDatabase) GetQuestionHex(hexid string, istemp bool) (q Question, er
|
||||
return f.GetQuestion(int64(binary.LittleEndian.Uint64(idb)), istemp)
|
||||
}
|
||||
|
||||
// GetMajors ...
|
||||
func (f *FileDatabase) GetMajors() (majors []string) {
|
||||
type majorq struct {
|
||||
Major string
|
||||
}
|
||||
var maj majorq
|
||||
f.mu.RLock()
|
||||
defer f.mu.RUnlock()
|
||||
f.db.QueryFor("SELECT DISTINCT Major FROM question;", &maj, func() error {
|
||||
majors = append(majors, maj.Major)
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// MaxDuplicateRate parse q.Dup and get the max rate
|
||||
func (q *Question) MaxDuplicateRate() float64 {
|
||||
dupmap := make(map[string]float64, 64)
|
||||
|
||||
Reference in New Issue
Block a user