Skip to content

Commit

Permalink
Add section removal in case of pageOverflow
Browse files Browse the repository at this point in the history
* Change service to builder patern
  • Loading branch information
Theo-Hafsaoui committed Nov 23, 2024
1 parent 4de166a commit 9fec15c
Show file tree
Hide file tree
Showing 6 changed files with 339 additions and 38 deletions.
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

run:
echo "Not yet complete"

Expand Down
16 changes: 9 additions & 7 deletions internal/adapters/input/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import (

//Use the implementation for markdown and latex to generate latex CV from a tree dir of mardown document
func GenerateCVFromMarkDownToLatex(root string)error{
var source core.Source = &MarkdownSource{}
var paramsSource core.SourceParams = &YamlSource{}
var templateReader core.TemplateReader = &output.LatexReader{}
var templateProccesor core.TemplateProcessor = &output.LatexProccesor{}
var compiler core.Compiler = &output.LatexCompiler{}
service := &core.CVService{}
return service.GenerateTemplates(root,source, paramsSource,templateReader,templateProccesor,compiler)
var builder core.BuilderService = core.BuilderService{}
builder.SetRoot(root)
builder.SetSource(&MarkdownSource{})
builder.SetParamsSource(&YamlSource{})
builder.SetTemplateReader(&output.LatexReader{})
builder.SetTemplateProcessor(&output.LatexProccesor{})
builder.SetCompiler(&output.LatexCompiler{})
service := builder.GetService()
return service.GenerateTemplates()
}
42 changes: 30 additions & 12 deletions internal/adapters/output/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,55 @@ import (
"log/slog"
"os"
"os/exec"
"regexp"
"strconv"
"strings"
"sync"
)


const COMPILER = "pdflatex"
var REGEX = regexp.MustCompile(`(\d+) page`)
type LatexCompiler struct{}

//Compile the template into PDF
func (*LatexCompiler) CompileTemplate(root string)error{
//Compile the templates into PDFs and return the number of page of the longest one
func (*LatexCompiler) CompileTemplate(root string)(int,error){
templates,err := getListOfTemplate(root);if err != nil {
return err
return 0,err
}
max_nb_of_page := 0
page_nb := make(chan int, len(templates))
var wg sync.WaitGroup
for _,template := range templates{
wg.Add(1)
go compile(template,root,&wg)
go compile(template,root,&wg, page_nb)
pdf_pages_nb := <-page_nb
slog.Info("Number of pages", "pages", pdf_pages_nb)
max_nb_of_page = max(pdf_pages_nb,max_nb_of_page)
}
close(page_nb)
wg.Wait()
return nil
return max_nb_of_page,nil
}

//Compile the template into a pdf
func compile(template string, root string, wg* sync.WaitGroup){
defer wg.Done()
cmd := exec.Command(COMPILER,"-interaction=nonstopmode",
"-output-directory="+root+"/assets/latex/output", template )
log, err := cmd.Output(); if err != nil {
slog.Info("---FROM pdflatex ---\n"+string(log))
slog.Error("failed to compile file:"+template)
func compile(template string, root string, wg* sync.WaitGroup, c_page_nb chan int){
defer wg.Done()
cmd := exec.Command(COMPILER,"-interaction=nonstopmode",
"-output-directory="+root+"/assets/latex/output", template )
log, err := cmd.Output(); if err != nil {
slog.Warn("error(s) to compile file:"+template)
}
page_nb := -1
log_page := REGEX.FindStringSubmatch(string(log))
if len(log_page)<1{
slog.Error("failed to compile file didnt get the number of pages:"+template)
fmt.Println(log_page)
}else{
page_nb,err = strconv.Atoi(log_page[1]);if err != nil{
slog.Error(err.Error())}
}
c_page_nb <- page_nb
}

//Return the path of latex file inside the template directory
Expand Down
139 changes: 127 additions & 12 deletions internal/core/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,93 @@ import (
"strings"
)

type CVService struct{}
type CVService struct{
root string
source Source
paramsSource SourceParams
templateReader TemplateReader
templateProcessor TemplateProcessor
compiler Compiler
}

type BuilderService struct{
root string
source Source
paramsSource SourceParams
templateReader TemplateReader
templateProcessor TemplateProcessor
compiler Compiler
}

func (cv *BuilderService) SetRoot(root string) {
cv.root = root
}

func (cv *BuilderService) SetSource(source Source) {
cv.source = source
}

func (cv *BuilderService) SetParamsSource(paramsSource SourceParams) {
cv.paramsSource = paramsSource
}

func (cv *BuilderService) SetTemplateReader(templateReader TemplateReader) {
cv.templateReader = templateReader
}

//generate the template for the cvs defined in the assets directory
func (g *CVService) GenerateTemplates(root string, source Source, paramsSource SourceParams,
templateReader TemplateReader, templateProcessor TemplateProcessor, compiler Compiler)error{
func (cv *BuilderService) SetTemplateProcessor(templateProcessor TemplateProcessor) {
cv.templateProcessor = templateProcessor
}

func (cv *BuilderService) SetCompiler(compiler Compiler) {
cv.compiler = compiler
}

func (s *BuilderService) GetService() CVService {
return CVService{
root: s.root,
source: s.source,
paramsSource: s.paramsSource,
templateReader: s.templateReader,
templateProcessor: s.templateProcessor,
compiler: s.compiler,
}
}


//generate the templates for the cvs defined in the assets directory
func (s *CVService) GenerateTemplates()error{
slog.Info("--Generating CVs--")
cvs,err := source.GetCVsFrom(root);if err != nil{ return err }
params,err := paramsSource.GetParamsFrom(root);if err != nil{ return err }
generiqueTemplate,err := templateReader.ReadCVTemplate(root,params); if err != nil{
cvs,err := s.source.GetCVsFrom(s.root);if err != nil{ return err }
params,err := s.paramsSource.GetParamsFrom(s.root);if err != nil{ return err }
generiqueTemplate,err := s.templateReader.ReadCVTemplate(s.root,params); if err != nil{
return err
}

for _, cv := range cvs {
err = generateCVFrom(cv,params,root,generiqueTemplate,templateProcessor)
err = generateCVFrom(cv,params,s.root,generiqueTemplate,s.templateProcessor,false)
if err != nil{
return err
}
}

err = compiler.CompileTemplate(root); if err != nil{ return err }
max_nb_page,err := s.compiler.CompileTemplate(s.root);
if err != nil{ }

Check failure on line 78 in internal/core/generate.go

View workflow job for this annotation

GitHub Actions / Run Linter

SA9003: empty branch (staticcheck)
for max_nb_page > 1{
for _, cv := range cvs {
err = generateCVFrom(cv,params,s.root,generiqueTemplate,s.templateProcessor,true)
if err != nil{
return err
}
}
max_nb_page,err = s.compiler.CompileTemplate(s.root);
if err != nil{ return nil }
}
return nil
}


//generate a template for the cv with the given params
func generateCVFrom(cv CV, params Params, root string,
template string, processor TemplateProcessor)(error){
template string, processor TemplateProcessor, shouldBeShorter bool)(error){
var err error
if len(params.Variante)==0{//if no variante create simple CV
params.Variante = map[string][]string{"simple": nil}
Expand All @@ -40,6 +101,9 @@ func generateCVFrom(cv CV, params Params, root string,
cvName := "CV-"+cv.Lang+"-"+vari+".tex"
slog.Info("Generating for:"+cvName)
cvTemplate := template
if shouldBeShorter {
removeLowestSection(&cv,keywords)
}
for _, section := range cv.Sections {
for _, paragraph := range section.Paragraphes {
headers := []string{ paragraph.H1, paragraph.H2,
Expand All @@ -57,6 +121,57 @@ func generateCVFrom(cv CV, params Params, root string,
return nil
}

//Sort items and after remove the last items
func removeLowestSection(cv *CV, keywords []string){
if len(cv.Sections)== 0{ return }
l_i := getLowestSection(*cv,keywords)
cv.Sections = append(cv.Sections[:l_i], cv.Sections[l_i+1:]...)
}

// Return the index of the section from the CV with the lowest score
func getLowestSection(cv CV, keywords []string) int {
return getLowestIndex(cv.Sections, keywords, getScoreSection)
}

// Return the index of the paragraph from the section with the lowest score
func getLowestParagraphe(section Section, keywords []string) int {
return getLowestIndex(section.Paragraphes, keywords, getScoreParagraphe)
}

//generic function to get the index of the element with the lowest score
//TODO ? an interface to avoid the any ?
func getLowestIndex[T any](items []T, keywords []string, getScore func(T, []string) int) int {
min_score := getScore(items[0], keywords)
min_idx := 0
for idx, item := range items[1:] {
current_score := getScore(item, keywords)
if current_score < min_score {
min_idx = idx + 1
min_score = current_score
}
}
return min_idx
}

//Get items of a section and sum they score to get global score of the items
func getScoreSection (section Section, keywords []string)int{
res := 0
for _, paragraph := range section.Paragraphes {
res+=getScoreParagraphe(paragraph,keywords)
}
return res
}

//Get items of a single paragraph and sum they score to get global score of the items
func getScoreParagraphe (paragraph Paragraphe, keywords []string)int{
res := 0
for _,item := range paragraph.Items{
res += getScore(item,keywords)
}
return res
}


//Sorte a slice of items by the number of keyword
//
//The sort is done in ascending order as the section append work like a stack(Lifo)
Expand Down
Loading

0 comments on commit 9fec15c

Please sign in to comment.