-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathentry.go
185 lines (171 loc) · 4.53 KB
/
entry.go
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// Copyright 2016-2018 mikan.
package chartgen
import (
"bufio"
"io/ioutil"
"net/http"
"strconv"
"strings"
"time"
)
type Workshop struct {
Title string `json:"title"`
ISBN string `json:"isbn"`
Pages int `json:"pages"`
Publisher string `json:"publisher"`
Published SimpleDate `json:"published"`
}
type Record struct {
Num int `json:"num"`
Workshop Workshop `json:"workshop"`
Date SimpleDate `json:"date"`
Attends []string `json:"attends"`
NotAttends []string `json:"not-attends"`
AttendsTotal int `json:"attends-total"`
Begin int `json:"begin,omitempty"`
End int `json:"end,omitempty"`
}
const titlePrefix = "title: "
const publisherPrefix = "* 出版: "
const publishedPrefix = "* 発売: "
const pagesPrefix = "* 頁数: "
const isbnPrefix = "* ISBN: "
const participantsPrefix = "| # | Date"
const participantPrefix = "![](/images/users/"
const recordPrefix = "| "
const (
titleFinding = iota
publisherFinding
publishedFinding
pagesFinding
isbnFinding
participantsFinding
recordFinding
ending
)
func FetchEntry(key string) string {
url := "https://raw.githubusercontent.com/aosn/aosn.github.io/master/workshop/" + key + ".md"
resp, err := http.Get(url)
if err != nil {
panic(err)
}
defer resp.Body.Close()
byteArray, _ := ioutil.ReadAll(resp.Body)
return string(byteArray)
}
func ParseEntry(markdown string) []Record {
var workshop Workshop
var records []Record
var users []string
state := titleFinding // initial parser state
scanner := bufio.NewScanner(strings.NewReader(markdown))
for scanner.Scan() {
line := scanner.Text()
switch state {
case titleFinding:
if strings.HasPrefix(line, titlePrefix) {
state = publisherFinding
workshop.Title = line[len(titlePrefix):]
}
case publisherFinding:
if strings.HasPrefix(line, publisherPrefix) {
state = publishedFinding
workshop.Publisher = strings.Replace(line[len(publisherPrefix):], " (訳書)", "", 1)
}
case publishedFinding:
if strings.HasPrefix(line, publishedPrefix) {
state = pagesFinding
format := "2006/01/02"
t, err := time.Parse(format, line[len(publishedPrefix):])
if err != nil {
panic(err) // invalid date format
}
workshop.Published = SimpleDate{t}
}
case pagesFinding:
if strings.HasPrefix(line, pagesPrefix) {
state = isbnFinding
pages, err := strconv.Atoi(line[len(pagesPrefix):])
if err != nil {
panic(err) // invalid number format
}
workshop.Pages = pages
}
case isbnFinding:
if strings.HasPrefix(line, isbnPrefix) {
state = participantsFinding
workshop.ISBN = line[len(isbnPrefix):]
}
case participantsFinding:
if strings.HasPrefix(line, participantsPrefix) {
for _, column := range strings.Split(line, "|") {
column := strings.Trim(column, " ")
if strings.HasPrefix(column, participantPrefix) {
for _, element := range strings.Split(column, " ") {
if strings.HasPrefix(element, participantPrefix) {
end := strings.Index(element, "_")
name := element[len(participantPrefix):end]
users = append(users, name)
}
}
break
} else {
continue
}
}
state = recordFinding
}
case recordFinding:
if strings.HasPrefix(line, recordPrefix) {
var record Record
var attends []string
var notAttends []string
record.Workshop = workshop
columns := strings.Split(line, "|")
// 1: #
num, err := strconv.Atoi(strings.Trim(columns[1], " "))
if err != nil {
state = ending // not a parse target
break
}
record.Num = num
// 2: Date & Time
format := "2006-01-02"
t, err := time.Parse(format, strings.Trim(columns[2], " ")[0:10])
if err != nil {
panic(err) // invalid date format
}
record.Date = SimpleDate{t}
// 3: A (unused)
total, err := strconv.Atoi(strings.Trim(columns[3], " "))
if err != nil {
state = ending
break
} else {
record.AttendsTotal = total
}
// 4: :o: / :x:
for n, ox := range strings.Replace(strings.Trim(columns[4], " "), ":", "", -1) {
switch ox {
case 'o':
attends = append(attends, users[n])
case 'x':
notAttends = append(notAttends, users[n])
}
}
// 5: p - p (or empty)
// 6: ex (unused)
record.Attends = attends
record.NotAttends = notAttends
records = append(records, record)
} else {
break
}
case ending:
break
default:
continue // continue finding
}
}
return records
}