1
0
mirror of https://github.com/fumiama/paper-manager.git synced 2026-06-25 05:20:16 +08:00

finish 试卷生成

This commit is contained in:
源文雨
2023-04-25 00:36:46 +08:00
parent aabd25ea19
commit 940b2618b3
10 changed files with 280 additions and 78 deletions

View File

@@ -4,10 +4,16 @@ import (
"encoding/json"
"io"
"net/http"
"os"
"time"
"github.com/FloatTech/ttl"
"github.com/fumiama/go-docx"
"github.com/fumiama/paper-manager/backend/global"
)
var genfilecache = ttl.NewCache[int, *docx.Docx](time.Minute * 10)
func init() {
apimap["/api/genFile"] = &apihandler{"POST", func(w http.ResponseWriter, r *http.Request) {
user := usertokens.Get(r.Header.Get("Authorization"))
@@ -27,6 +33,21 @@ func init() {
writeresult(w, codeError, nil, err.Error(), typeError)
return
}
genfilecache.Set(*user.ID, docf)
writeresult(w, codeSuccess, "请在10分钟内下载, 且不要在下载完成前关闭页面, 云端不会保存", messageOk, typeSuccess)
}}
apimap["/api/dlGen"] = &apihandler{"GET", func(w http.ResponseWriter, r *http.Request) {
user := usertokens.Get(r.Header.Get("Authorization"))
if user == nil {
writeresult(w, codeError, nil, errInvalidToken.Error(), typeError)
return
}
docf := genfilecache.Get(*user.ID)
if docf == nil {
writeresult(w, codeError, nil, os.ErrNotExist.Error(), typeError)
return
}
_, _ = io.Copy(w, docf)
}}
}

View File

@@ -53,7 +53,7 @@ func init() {
panic(err)
}
err = FileDB.db.Create(FileTableQuestion, &Question{},
"FOREIGN KEY(FileID) REFERENCES "+FileTableFile+"(ID)",
"FOREIGN KEY(ListID) REFERENCES "+FileTableList+"(ID)",
)
if err != nil {
panic(err)

View File

@@ -7,11 +7,13 @@ import (
sql "github.com/FloatTech/sqlite"
"github.com/fumiama/go-docx"
"github.com/sirupsen/logrus"
)
var (
ErrInvalidGenerateConfig = errors.New("invalid generate config")
ErrMajorTooLarge = errors.New("major too large")
ErrNoSuchMajor = errors.New("no such major")
ErrNoEnoughQuestionToMatchRequire = errors.New("no enough question to match require")
ErrRateLimitExceeded = errors.New("rate limit exceeded")
)
@@ -26,21 +28,31 @@ type GenerateConfig struct {
}
// GenerateFile 用一些限定条件生成新试卷, 云端不保存
func (f *FileDatabase) GenerateFile(config *GenerateConfig) (*docx.Docx, error) {
func (f *FileDatabase) GenerateFile(config *GenerateConfig) (docf *docx.Docx, err 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()
mm := map[string]struct{}{}
for _, m := range f.GetMajors() {
mm[m] = struct{}{}
}
for n := range config.Distribution {
if _, ok := mm[n]; !ok {
return nil, ErrNoSuchMajor
}
}
docf = docx.NewA4()
f.mu.RLock()
defer f.mu.RUnlock()
i := 0
for n, c := range config.Distribution {
if c == 0 {
if c <= 0 {
continue
}
docf.AddParagraph().AddText(string([]rune("一二三四五六七八九十")[c]) + "、" + n).Size("44").Bold()
docf.AddParagraph().AddText(string([]rune("一二三四五六七八九十")[i]) + "、" + n).Size("30").Bold()
cond := " WHERE"
hasfront := false
if config.YearStart > 0 {
@@ -51,20 +63,32 @@ func (f *FileDatabase) GenerateFile(config *GenerateConfig) (*docx.Docx, error)
if hasfront {
cond += " AND"
}
cond += " Year<=" + strconv.Itoa(int(config.YearStart))
cond += " Year<=" + strconv.Itoa(int(config.YearEnd))
hasfront = true
}
if hasfront {
cond += " AND"
if config.TypeMask > 0 {
if hasfront {
cond += " AND"
}
typmsk := strconv.Itoa(int(config.TypeMask))
cond += " (Type&" + typmsk + ")==" + typmsk
hasfront = true
}
var ques []*Question
q := ""
if hasfront {
q = "SELECT * FROM " + FileTableQuestion +
" WHERE Major='" + n + "' AND ListID IN (SELECT DISTINCT ListID FROM " +
FileTableFile + cond +
") ORDER BY RANDOM() limit " + strconv.Itoa(int(c)) + ";"
ques, err = sql.QueryAll[Question](&f.db, q)
} else {
q = "SELECT * FROM " + FileTableQuestion +
" WHERE Major='" + n + "' ORDER BY RANDOM() limit " + strconv.Itoa(int(c)) + ";"
ques, err = sql.QueryAll[Question](&f.db, q)
}
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 {
logrus.Warnln(err, q)
return nil, err
}
if len(ques) != int(c) {
@@ -79,7 +103,7 @@ func (f *FileDatabase) GenerateFile(config *GenerateConfig) (*docx.Docx, error)
return nil, ErrRateLimitExceeded
}
for i, q := range ques {
lst, err := sql.Find[List](&f.db, FileTableFile, "WHERE ID="+strconv.Itoa(q.ListID))
lst, err := sql.Find[List](&f.db, FileTableList, "WHERE ID="+strconv.Itoa(q.ListID))
if err != nil {
return nil, err
}
@@ -98,6 +122,7 @@ func (f *FileDatabase) GenerateFile(config *GenerateConfig) (*docx.Docx, error)
docf.AddParagraph().AddText(strconv.Itoa(i+1) + ". (" + lst.Desc + ")")
docf.AppendFile(docq)
}
i++
}
return docf, nil
}