move: log parser

This commit is contained in:
Inanc Gumus
2019-08-21 20:38:07 +03:00
parent 6dc3774fc0
commit 8cb42216e4
73 changed files with 2 additions and 2 deletions

View File

@@ -0,0 +1,20 @@
### PROBLEM
+ `summarize()` knows a lot about the internals of the `parser`.
+ coupled to the `parser`.
## SOLUTION
+ remove: `parser.go` `sum` and `domains` fields
+ remove: `parser.go/newParser()`
+ change: `parser.go/parse(p *parser) error` -> `parse() ([]result, error)`
+ initialize: `sum` inside `parse()`
+ remove: `update()`
+ call: `sum` update in the `parse()`
+ collect the grouped results and return them from `parser()`
+ `summarize(p *parser)` -> `summarize([]result)`
+ in `summarize()`
+ `sort.Slice`
+ range over `[]result`
+ `main.go`
+ just: `res, err := parse()`

View File

@@ -0,0 +1,22 @@
// For more tutorials: https://blog.learngoprogramming.com
//
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
package main
import (
"fmt"
)
func main() {
res, err := parse()
if err != nil {
fmt.Println("> Err:", err)
return
}
summarize(res)
}

View File

@@ -0,0 +1,48 @@
// For more tutorials: https://blog.learngoprogramming.com
//
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
package main
import (
"bufio"
"fmt"
"os"
)
// parser keeps track of the parsing
type parser struct {
}
// parse the log lines and return results
func parse() ([]result, error) {
var (
l = 1
in = bufio.NewScanner(os.Stdin)
sum = make(map[string]result)
)
// parse the log lines
for in.Scan() {
r, err := parseResult(in.Text())
if err != nil {
return nil, fmt.Errorf("line %d: %v", l, err)
}
l++
// group the log lines by domain
sum[r.domain] = addResult(r, sum[r.domain])
}
// collect the grouped results
res := make([]result, 0, len(sum))
for _, r := range sum {
res = append(res, r)
}
return res, in.Err()
}

View File

@@ -0,0 +1,53 @@
// For more tutorials: https://blog.learngoprogramming.com
//
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
package main
import (
"fmt"
"strconv"
"strings"
)
const fieldsLength = 4
// result stores the parsed result for a domain
type result struct {
domain, page string
visits, uniques int
// add more metrics if needed
}
// parseResult from a log line
func parseResult(line string) (r result, err error) {
fields := strings.Fields(line)
if len(fields) != fieldsLength {
return r, fmt.Errorf("wrong input: %v", fields)
}
r.domain = fields[0]
r.page = fields[1]
r.visits, err = strconv.Atoi(fields[2])
if err != nil || r.visits < 0 {
return r, fmt.Errorf("wrong input: %q", fields[2])
}
r.uniques, err = strconv.Atoi(fields[3])
if err != nil || r.uniques < 0 {
return r, fmt.Errorf("wrong input: %q", fields[3])
}
return r, nil
}
// addResult to another one
func addResult(r, other result) result {
r.visits += other.visits
r.uniques += other.uniques
return r
}

View File

@@ -0,0 +1,49 @@
// For more tutorials: https://blog.learngoprogramming.com
//
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
package main
import (
"fmt"
"sort"
"strings"
)
// summarize summarizes and prints the parsing result
// + violation: accesses the parsing internals: p.domains + p.sum + p.total
// + give it the []result only.
// + let it calculate the total.
const (
// DOMAINS PAGES VISITS UNIQUES
// ^ ^ ^ ^
// | | | |
header = "%-25s %-10s %10s %10s\n"
line = "%-25s %-10s %10d %10d\n"
footer = "\n%-36s %10d %10d\n" // -> "" VISITS UNIQUES
dash = "-"
dashLength = 58
)
// summarize summarizes and prints the parsing result
func summarize(res []result) {
// sort.Strings(p.domains)
sort.Slice(res, func(i, j int) bool {
return res[i].domain <= res[j].domain
})
fmt.Printf(header, "DOMAIN", "PAGES", "VISITS", "UNIQUES")
fmt.Println(strings.Repeat("-", dashLength))
var total result
for _, r := range res {
total = addResult(total, r)
fmt.Printf(line, r.domain, r.page, r.visits, r.uniques)
}
fmt.Printf(footer, "TOTAL", total.visits, total.uniques)
}