Files
LeetCode-Go/ctl/render.go
2021-01-15 22:32:12 +08:00

243 lines
7.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"bufio"
"encoding/json"
"fmt"
m "github.com/halfrost/LeetCode-Go/ctl/models"
"github.com/halfrost/LeetCode-Go/ctl/util"
"github.com/spf13/cobra"
"io"
"os"
"regexp"
"sort"
"strconv"
"strings"
)
var (
chapterTwoList = []string{"Array", "String", "Two Pointers", "Linked List", "Stack", "Tree", "Dynamic Programming", "Backtracking", "Depth First Search", "Breadth First Search",
"Binary Search", "Math", "Hash Table", "Sort", "Bit Manipulation", "Union Find", "Sliding Window", "Segment Tree", "Binary Indexed Tree"}
chapterTwoFileName = []string{"Array", "String", "Two_Pointers", "Linked_List", "Stack", "Tree", "Dynamic_Programming", "Backtracking", "Depth_First_Search", "Breadth_First_Search",
"Binary_Search", "Math", "Hash_Table", "Sort", "Bit_Manipulation", "Union_Find", "Sliding_Window", "Segment_Tree", "Binary_Indexed_Tree"}
chapterTwoSlug = []string{"array", "string", "two-pointers", "linked-list", "stack", "tree", "dynamic-programming", "backtracking", "depth-first-search", "breadth-first-search",
"binary-search", "math", "hash-table", "sort", "bit-manipulation", "union-find", "sliding-window", "segment-tree", "binary-indexed-tree"}
)
func newBuildCommand() *cobra.Command {
mc := &cobra.Command{
Use: "build <subcommand>",
Short: "Build doc related commands",
}
//mc.PersistentFlags().StringVar(&logicEndpoint, "endpoint", "localhost:5880", "endpoint of logic service")
mc.AddCommand(
newBuildREADME(),
newBuildChapterTwo(),
)
return mc
}
func newBuildREADME() *cobra.Command {
cmd := &cobra.Command{
Use: "readme",
Short: "Build readme.md commands",
Run: func(cmd *cobra.Command, args []string) {
buildREADME()
},
}
// cmd.Flags().StringVar(&alias, "alias", "", "alias")
// cmd.Flags().StringVar(&appId, "appid", "", "appid")
return cmd
}
func newBuildChapterTwo() *cobra.Command {
cmd := &cobra.Command{
Use: "chapter-two",
Short: "Build Chapter Two commands",
Run: func(cmd *cobra.Command, args []string) {
buildChapterTwo()
},
}
// cmd.Flags().StringVar(&alias, "alias", "", "alias")
// cmd.Flags().StringVar(&appId, "appid", "", "appid")
return cmd
}
func buildREADME() {
var (
problems []m.StatStatusPairs
lpa m.LeetCodeProblemAll
info m.UserInfo
)
// 请求所有题目信息
body := getProblemAllList()
problemsMap, optimizingIds := map[int]m.StatStatusPairs{}, []int{}
err := json.Unmarshal(body, &lpa)
if err != nil {
fmt.Println(err)
return
}
//writeFile("leetcode_problem.json", body)
// 拼凑 README 需要渲染的数据
problems = lpa.StatStatusPairs
info = m.ConvertUserInfoModel(lpa)
for _, v := range problems {
problemsMap[int(v.Stat.FrontendQuestionID)] = v
}
mdrows := m.ConvertMdModelFromSsp(problems)
sort.Sort(m.SortByQuestionID(mdrows))
solutionIds, try := util.LoadSolutionsDir()
m.GenerateMdRows(solutionIds, mdrows)
info.EasyTotal, info.MediumTotal, info.HardTotal, info.OptimizingEasy, info.OptimizingMedium, info.OptimizingHard, optimizingIds = statisticalData(problemsMap, solutionIds)
omdrows := m.ConvertMdModelFromIds(problemsMap, optimizingIds)
sort.Sort(m.SortByQuestionID(omdrows))
// 按照模板渲染 README
res, err := renderReadme("./template/template.markdown", len(solutionIds), try, m.Mdrows{Mdrows: mdrows}, m.Mdrows{Mdrows: omdrows}, info)
if err != nil {
fmt.Println(err)
return
}
util.WriteFile("../README.md", res)
//makeReadmeFile(mds)
}
func renderReadme(filePath string, total, try int, mdrows, omdrows m.Mdrows, user m.UserInfo) ([]byte, error) {
f, err := os.OpenFile(filePath, os.O_RDONLY, 0644)
if err != nil {
return nil, err
}
defer f.Close()
reader, output := bufio.NewReader(f), []byte{}
for {
line, _, err := reader.ReadLine()
if err != nil {
if err == io.EOF {
return output, nil
}
return nil, err
}
if ok, _ := regexp.Match("{{.AvailableTable}}", line); ok {
reg := regexp.MustCompile("{{.AvailableTable}}")
newByte := reg.ReplaceAll(line, []byte(mdrows.AvailableTable()))
output = append(output, newByte...)
output = append(output, []byte("\n")...)
} else if ok, _ := regexp.Match("{{.TotalNum}}", line); ok {
reg := regexp.MustCompile("{{.TotalNum}}")
newByte := reg.ReplaceAll(line, []byte(fmt.Sprintf("以下已经收录了 %v 道题的题解,还有 %v 道题在尝试优化到 beats 100%%", total, try)))
output = append(output, newByte...)
output = append(output, []byte("\n")...)
} else if ok, _ := regexp.Match("{{.PersonalData}}", line); ok {
reg := regexp.MustCompile("{{.PersonalData}}")
newByte := reg.ReplaceAll(line, []byte(user.PersonalData()))
output = append(output, newByte...)
output = append(output, []byte("\n")...)
} else if ok, _ := regexp.Match("{{.OptimizingTable}}", line); ok {
reg := regexp.MustCompile("{{.OptimizingTable}}")
newByte := reg.ReplaceAll(line, []byte(fmt.Sprintf("以下 %v 道题还需要优化到 100%% 的题目列表\n\n%v", (user.OptimizingEasy+user.OptimizingMedium+user.OptimizingHard), omdrows.AvailableTable())))
output = append(output, newByte...)
output = append(output, []byte("\n")...)
} else {
output = append(output, line...)
output = append(output, []byte("\n")...)
}
}
}
func buildChapterTwo() {
var (
gr m.GraphQLResp
questions []m.Question
)
for index, tag := range chapterTwoSlug {
body := getTagProblemList(tag)
// fmt.Printf("%v\n", string(body))
err := json.Unmarshal(body, &gr)
if err != nil {
fmt.Println(err)
return
}
questions = gr.Data.TopicTag.Questions
mdrows := m.ConvertMdModelFromQuestions(questions)
sort.Sort(m.SortByQuestionID(mdrows))
solutionIds, _ := util.LoadSolutionsDir()
// generateMdRows(solutionIds, mdrows)
tl, err := loadMetaData(fmt.Sprintf("./meta/%v", chapterTwoFileName[index]))
if err != nil {
fmt.Printf("err = %v\n", err)
}
tls := m.GenerateTagMdRows(solutionIds, tl, mdrows)
//fmt.Printf("tls = %v\n", tls)
// // 按照模板渲染 README
res, err := renderChapterTwo(fmt.Sprintf("./template/%v.md", chapterTwoFileName[index]), m.TagLists{TagLists: tls})
if err != nil {
fmt.Println(err)
return
}
util.WriteFile(fmt.Sprintf("./%v.md", chapterTwoFileName[index]), res)
}
}
func loadMetaData(filePath string) (map[int]m.TagList, error) {
f, err := os.OpenFile(filePath, os.O_RDONLY, 0644)
if err != nil {
return nil, err
}
defer f.Close()
reader, metaMap := bufio.NewReader(f), map[int]m.TagList{}
for {
line, _, err := reader.ReadLine()
if err != nil {
if err == io.EOF {
return metaMap, nil
}
return nil, err
}
s := strings.Split(string(line), "|")
v, _ := strconv.Atoi(strings.Split(s[1], ".")[0])
// v[0] 是题号s[4] time, s[5] space, s[6] favorite
metaMap[v] = m.TagList{
FrontendQuestionID: int32(v),
Acceptance: "",
Difficulty: "",
TimeComplexity: s[4],
SpaceComplexity: s[5],
Favorite: s[6],
}
}
}
func renderChapterTwo(filePath string, tls m.TagLists) ([]byte, error) {
f, err := os.OpenFile(filePath, os.O_RDONLY, 0644)
if err != nil {
return nil, err
}
defer f.Close()
reader, output := bufio.NewReader(f), []byte{}
for {
line, _, err := reader.ReadLine()
if err != nil {
if err == io.EOF {
return output, nil
}
return nil, err
}
if ok, _ := regexp.Match("{{.AvailableTagTable}}", line); ok {
reg := regexp.MustCompile("{{.AvailableTagTable}}")
newByte := reg.ReplaceAll(line, []byte(tls.AvailableTagTable()))
output = append(output, newByte...)
output = append(output, []byte("\n")...)
} else {
output = append(output, line...)
output = append(output, []byte("\n")...)
}
}
}