aboutsummaryrefslogtreecommitdiff
path: root/projects/project.go
blob: 85239c96af5299df63fe2f5ea5f9e6a0d9558ad2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package projects

import (
	"encoding/json"
	"html/template"
	"log"
	"math"
	"os"
	"path"
	"strings"
)

type Link struct {
	Title string
	Href  string
	Class string `json:",omitempty"`
}

type Project struct {
	Name string `json:"-"`

	Title       string
	Description string
	Shortdesc   string
	GoGet       string `json:",omitempty"`
	ReadmePath  string `json:",omitempty"`
	Git         string `json:",omitempty"` // local git repo
	License     string `json:",omitempty"`
	Links       []Link
	Tags        []string

	dir             string        `json:"-"`
	FormattedReadme template.HTML `json:"-"`
}

func LoadProject(name string) (p Project, err error) {
	f, err := os.Open(name)
	if err != nil {
		return p, err
	}
	defer f.Close()

	dec := json.NewDecoder(f)
	if err := dec.Decode(&p); err != nil {
		return p, err
	}

	p.dir = path.Dir(name)
	p.formatReadme()
	p.Name = strings.Split(path.Base(name), ".")[0]

	return
}

type ProjectRepo struct {
	Dir      string
	Projects map[string]Project
	Tags     map[string]map[string]struct{}
	Tagcloud map[string]TagcloudElem
}

const TAGCLOUD_SIZE_CATEGORIES = 5

type TagcloudElem struct {
	Tag  string
	Size int
}

func NewProjectRepo(dir string) *ProjectRepo {
	return &ProjectRepo{
		Dir:      dir,
		Projects: make(map[string]Project),
		Tags:     make(map[string]map[string]struct{}),
		Tagcloud: make(map[string]TagcloudElem),
	}
}

func (repo *ProjectRepo) updateTags() {
	tags := make(map[string]map[string]struct{})
	tagcounts := make(map[string]int)
	maxcount := 0

	for name, proj := range repo.Projects {
		for _, tag := range proj.Tags {
			if _, ok := tags[tag]; !ok {
				tags[tag] = make(map[string]struct{})
			}
			tags[tag][name] = struct{}{}

			tagcount := tagcounts[tag] + 1
			tagcounts[tag] = tagcount
			if tagcount > maxcount {
				maxcount = tagcount
			}
		}
	}

	tagcloud := make(map[string]TagcloudElem)
	if maxcount > 0 {
		for tag, count := range tagcounts {
			tagcloud[tag] = TagcloudElem{
				Tag:  tag,
				Size: int(math.Ceil((float64(count) / float64(maxcount)) * TAGCLOUD_SIZE_CATEGORIES)),
			}
		}
	}

	repo.Tags = tags
	repo.Tagcloud = tagcloud
}

func (repo *ProjectRepo) ScanProjects() {
	d, err := os.Open(repo.Dir)
	if err != nil {
		log.Printf("Failed scanning projects: Could not open dir: %s", err)
		return
	}
	defer d.Close()

	names, err := d.Readdirnames(0)
	if err != nil {
		log.Printf("Failed scanning projects: Could not readdir: %s", err)
		return
	}

	projects := make(map[string]Project)

	for _, fname := range names {
		if path.Ext(fname) != ".json" {
			continue
		}

		p, err := LoadProject(path.Join(repo.Dir, fname))
		if err != nil {
			log.Printf("Skip project file %s: %s", fname, err)
			continue
		}

		projects[p.Name] = p
	}

	repo.Projects = projects
	repo.updateTags()
}