rename: oop log parser result -> record
This commit is contained in:
		| @@ -8,7 +8,7 @@ package main | |||||||
| // 	width, height int | // 	width, height int | ||||||
| // } | // } | ||||||
|  |  | ||||||
| // func (s *chartReport) digest(results iterator) error { | // func (s *chartReport) digest(records iterator) error { | ||||||
| // 	w := os.Stdout | // 	w := os.Stdout | ||||||
|  |  | ||||||
| // 	donut := chart.DonutChart{ | // 	donut := chart.DonutChart{ | ||||||
| @@ -22,7 +22,7 @@ package main | |||||||
| // 		Height: s.height, | // 		Height: s.height, | ||||||
| // 	} | // 	} | ||||||
|  |  | ||||||
| // 	results.each(func(r result) { | // 	records.each(func(r record) { | ||||||
| // 		v := chart.Value{ | // 		v := chart.Value{ | ||||||
| // 			Label: r.domain + r.page + ": " + strconv.Itoa(r.visits), | // 			Label: r.domain + r.page + ": " + strconv.Itoa(r.visits), | ||||||
| // 			Value: float64(r.visits), | // 			Value: float64(r.visits), | ||||||
|   | |||||||
| @@ -16,15 +16,15 @@ func filterBy(fn ...filterFunc) *filter { | |||||||
| 	return &filter{filters: fn} | 	return &filter{filters: fn} | ||||||
| } | } | ||||||
|  |  | ||||||
| // transform the result | // transform the record | ||||||
| func (f *filter) digest(results iterator) error { | func (f *filter) digest(records iterator) error { | ||||||
| 	f.src = results | 	f.src = records | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // each yields an analysis result | // each yields only the filtered records | ||||||
| func (f *filter) each(yield resultFn) error { | func (f *filter) each(yield recordFn) error { | ||||||
| 	return f.src.each(func(r result) { | 	return f.src.each(func(r record) { | ||||||
| 		if !f.check(r) { | 		if !f.check(r) { | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| @@ -32,8 +32,8 @@ func (f *filter) each(yield resultFn) error { | |||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  |  | ||||||
| // check all the filters against the result | // check all the filters against the record | ||||||
| func (f *filter) check(r result) bool { | func (f *filter) check(r record) bool { | ||||||
| 	for _, fi := range f.filters { | 	for _, fi := range f.filters { | ||||||
| 		if !fi(r) { | 		if !fi(r) { | ||||||
| 			return false | 			return false | ||||||
|   | |||||||
| @@ -2,20 +2,20 @@ package main | |||||||
|  |  | ||||||
| import "strings" | import "strings" | ||||||
|  |  | ||||||
| type filterFunc func(result) bool | type filterFunc func(record) bool | ||||||
|  |  | ||||||
| func noopFilter(r result) bool { | func noopFilter(r record) bool { | ||||||
| 	return true | 	return true | ||||||
| } | } | ||||||
|  |  | ||||||
| func notUsing(filter filterFunc) filterFunc { | func notUsing(filter filterFunc) filterFunc { | ||||||
| 	return func(r result) bool { | 	return func(r record) bool { | ||||||
| 		return !filter(r) | 		return !filter(r) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func domainExtFilter(domains ...string) filterFunc { | func domainExtFilter(domains ...string) filterFunc { | ||||||
| 	return func(r result) bool { | 	return func(r record) bool { | ||||||
| 		for _, domain := range domains { | 		for _, domain := range domains { | ||||||
| 			if strings.HasSuffix(r.domain, "."+domain) { | 			if strings.HasSuffix(r.domain, "."+domain) { | ||||||
| 				return true | 				return true | ||||||
| @@ -26,11 +26,11 @@ func domainExtFilter(domains ...string) filterFunc { | |||||||
| } | } | ||||||
|  |  | ||||||
| func domainFilter(domain string) filterFunc { | func domainFilter(domain string) filterFunc { | ||||||
| 	return func(r result) bool { | 	return func(r record) bool { | ||||||
| 		return strings.Contains(r.domain, domain) | 		return strings.Contains(r.domain, domain) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func orgDomainsFilter(r result) bool { | func orgDomainsFilter(r record) bool { | ||||||
| 	return strings.HasSuffix(r.domain, ".org") | 	return strings.HasSuffix(r.domain, ".org") | ||||||
| } | } | ||||||
|   | |||||||
| @@ -12,21 +12,21 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| type group struct { | type group struct { | ||||||
| 	sum  map[string]result // metrics per group key | 	sum  map[string]record // metrics per group key | ||||||
| 	keys []string          // unique group keys | 	keys []string          // unique group keys | ||||||
| 	key  groupFunc | 	key  groupFunc | ||||||
| } | } | ||||||
|  |  | ||||||
| func groupBy(key groupFunc) *group { | func groupBy(key groupFunc) *group { | ||||||
| 	return &group{ | 	return &group{ | ||||||
| 		sum: make(map[string]result), | 		sum: make(map[string]record), | ||||||
| 		key: key, | 		key: key, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // digest the results | // digest the records | ||||||
| func (g *group) digest(results iterator) error { | func (g *group) digest(records iterator) error { | ||||||
| 	return results.each(func(r result) { | 	return records.each(func(r record) { | ||||||
| 		k := g.key(r) | 		k := g.key(r) | ||||||
|  |  | ||||||
| 		if _, ok := g.sum[k]; !ok { | 		if _, ok := g.sum[k]; !ok { | ||||||
| @@ -37,8 +37,8 @@ func (g *group) digest(results iterator) error { | |||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  |  | ||||||
| // each yields the grouped results | // each yields the grouped records | ||||||
| func (g *group) each(yield resultFn) error { | func (g *group) each(yield recordFn) error { | ||||||
| 	sort.Strings(g.keys) | 	sort.Strings(g.keys) | ||||||
|  |  | ||||||
| 	for _, k := range g.keys { | 	for _, k := range g.keys { | ||||||
|   | |||||||
| @@ -1,15 +1,15 @@ | |||||||
| package main | package main | ||||||
|  |  | ||||||
| type groupFunc func(result) string | type groupFunc func(record) string | ||||||
|  |  | ||||||
| // domainGrouper groups by domain. | // domainGrouper groups by domain. | ||||||
| // but it keeps the other fields. | // but it keeps the other fields. | ||||||
| // for example: it returns pages as well, but you shouldn't use them. | // for example: it returns pages as well, but you shouldn't use them. | ||||||
| // exercise: write a function that erases the unnecessary data. | // exercise: write a function that erases the unnecessary data. | ||||||
| func domainGrouper(r result) string { | func domainGrouper(r record) string { | ||||||
| 	return r.domain | 	return r.domain | ||||||
| } | } | ||||||
|  |  | ||||||
| func pageGrouper(r result) string { | func pageGrouper(r record) string { | ||||||
| 	return r.domain + r.page | 	return r.domain + r.page | ||||||
| } | } | ||||||
|   | |||||||
| @@ -21,13 +21,13 @@ func newJSONLog(r io.Reader) *jsonLog { | |||||||
| 	return &jsonLog{reader: r} | 	return &jsonLog{reader: r} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (j *jsonLog) each(yield resultFn) error { | func (j *jsonLog) each(yield recordFn) error { | ||||||
| 	defer readClose(j.reader) | 	defer readClose(j.reader) | ||||||
|  |  | ||||||
| 	dec := json.NewDecoder(bufio.NewReader(j.reader)) | 	dec := json.NewDecoder(bufio.NewReader(j.reader)) | ||||||
|  |  | ||||||
| 	for { | 	for { | ||||||
| 		var r result | 		var r record | ||||||
|  |  | ||||||
| 		err := dec.Decode(&r) | 		err := dec.Decode(&r) | ||||||
| 		if err == io.EOF { | 		if err == io.EOF { | ||||||
|   | |||||||
| @@ -15,8 +15,8 @@ type logCount struct { | |||||||
| 	n int | 	n int | ||||||
| } | } | ||||||
|  |  | ||||||
| func (lc *logCount) each(yield resultFn) error { | func (lc *logCount) each(yield recordFn) error { | ||||||
| 	err := lc.iterator.each(func(r result) { | 	err := lc.iterator.each(func(r record) { | ||||||
| 		lc.n++ | 		lc.n++ | ||||||
| 		yield(r) | 		yield(r) | ||||||
| 	}) | 	}) | ||||||
|   | |||||||
| @@ -13,9 +13,9 @@ import ( | |||||||
| 	"strings" | 	"strings" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type resultFn func(result) | type recordFn func(record) | ||||||
|  |  | ||||||
| type iterator interface{ each(resultFn) error } | type iterator interface{ each(recordFn) error } | ||||||
| type digester interface{ digest(iterator) error } | type digester interface{ digest(iterator) error } | ||||||
|  |  | ||||||
| type transform interface { | type transform interface { | ||||||
|   | |||||||
| @@ -10,21 +10,21 @@ import ( | |||||||
| 
 | 
 | ||||||
| const fieldsLength = 4 | const fieldsLength = 4 | ||||||
| 
 | 
 | ||||||
| type result struct { | type record struct { | ||||||
| 	domain  string | 	domain  string | ||||||
| 	page    string | 	page    string | ||||||
| 	visits  int | 	visits  int | ||||||
| 	uniques int | 	uniques int | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (r result) sum(other result) result { | func (r record) sum(other record) record { | ||||||
| 	r.visits += other.visits | 	r.visits += other.visits | ||||||
| 	r.uniques += other.uniques | 	r.uniques += other.uniques | ||||||
| 	return r | 	return r | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // UnmarshalText to a *result | // UnmarshalText to a *record | ||||||
| func (r *result) UnmarshalText(p []byte) (err error) { | func (r *record) UnmarshalText(p []byte) (err error) { | ||||||
| 	fields := strings.Fields(string(p)) | 	fields := strings.Fields(string(p)) | ||||||
| 	if len(fields) != fieldsLength { | 	if len(fields) != fieldsLength { | ||||||
| 		return fmt.Errorf("wrong number of fields %q", fields) | 		return fmt.Errorf("wrong number of fields %q", fields) | ||||||
| @@ -41,8 +41,8 @@ func (r *result) UnmarshalText(p []byte) (err error) { | |||||||
| 	return validate(*r) | 	return validate(*r) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // UnmarshalJSON to a *result | // UnmarshalJSON to a *record | ||||||
| func (r *result) UnmarshalJSON(data []byte) error { | func (r *record) UnmarshalJSON(data []byte) error { | ||||||
| 	var re struct { | 	var re struct { | ||||||
| 		Domain  string | 		Domain  string | ||||||
| 		Page    string | 		Page    string | ||||||
| @@ -54,7 +54,7 @@ func (r *result) UnmarshalJSON(data []byte) error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	*r = result{re.Domain, re.Page, re.Visits, re.Uniques} | 	*r = record{re.Domain, re.Page, re.Visits, re.Uniques} | ||||||
| 	return validate(*r) | 	return validate(*r) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @@ -62,21 +62,21 @@ func (r *result) UnmarshalJSON(data []byte) error { | |||||||
| func parseStr(name, v string) (int, error) { | func parseStr(name, v string) (int, error) { | ||||||
| 	n, err := strconv.Atoi(v) | 	n, err := strconv.Atoi(v) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return 0, fmt.Errorf("result.UnmarshalText %q: %v", name, err) | 		return 0, fmt.Errorf("record.UnmarshalText %q: %v", name, err) | ||||||
| 	} | 	} | ||||||
| 	return n, nil | 	return n, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func validate(r result) (err error) { | func validate(r record) (err error) { | ||||||
| 	switch { | 	switch { | ||||||
| 	case r.domain == "": | 	case r.domain == "": | ||||||
| 		err = errors.New("result.domain cannot be empty") | 		err = errors.New("record.domain cannot be empty") | ||||||
| 	case r.page == "": | 	case r.page == "": | ||||||
| 		err = errors.New("result.page cannot be empty") | 		err = errors.New("record.page cannot be empty") | ||||||
| 	case r.visits < 0: | 	case r.visits < 0: | ||||||
| 		err = errors.New("result.visits cannot be negative") | 		err = errors.New("record.visits cannot be negative") | ||||||
| 	case r.uniques < 0: | 	case r.uniques < 0: | ||||||
| 		err = errors.New("result.uniques cannot be negative") | 		err = errors.New("record.uniques cannot be negative") | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| @@ -20,13 +20,13 @@ func newTextLog(r io.Reader) *textLog { | |||||||
| 	return &textLog{reader: r} | 	return &textLog{reader: r} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (p *textLog) each(yield resultFn) error { | func (p *textLog) each(yield recordFn) error { | ||||||
| 	defer readClose(p.reader) | 	defer readClose(p.reader) | ||||||
|  |  | ||||||
| 	in := bufio.NewScanner(p.reader) | 	in := bufio.NewScanner(p.reader) | ||||||
|  |  | ||||||
| 	for in.Scan() { | 	for in.Scan() { | ||||||
| 		r := new(result) | 		r := new(record) | ||||||
|  |  | ||||||
| 		if err := r.UnmarshalText(in.Bytes()); err != nil { | 		if err := r.UnmarshalText(in.Bytes()); err != nil { | ||||||
| 			return err | 			return err | ||||||
|   | |||||||
| @@ -27,7 +27,7 @@ func newTextReport() *textReport { | |||||||
| 	return new(textReport) | 	return new(textReport) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *textReport) digest(results iterator) error { | func (s *textReport) digest(records iterator) error { | ||||||
| 	w := tabwriter.NewWriter(os.Stdout, minWidth, tabWidth, padding, ' ', flags) | 	w := tabwriter.NewWriter(os.Stdout, minWidth, tabWidth, padding, ' ', flags) | ||||||
|  |  | ||||||
| 	write := fmt.Fprintf | 	write := fmt.Fprintf | ||||||
| @@ -35,8 +35,8 @@ func (s *textReport) digest(results iterator) error { | |||||||
| 	write(w, "DOMAINS\tPAGES\tVISITS\tUNIQUES\n") | 	write(w, "DOMAINS\tPAGES\tVISITS\tUNIQUES\n") | ||||||
| 	write(w, "-------\t-----\t------\t-------\n") | 	write(w, "-------\t-----\t------\t-------\n") | ||||||
|  |  | ||||||
| 	var total result | 	var total record | ||||||
| 	results.each(func(r result) { | 	records.each(func(r record) { | ||||||
| 		total = total.sum(r) | 		total = total.sum(r) | ||||||
|  |  | ||||||
| 		write(w, "%s\t%s\t%d\t%d\n", r.domain, r.page, r.visits, r.uniques) | 		write(w, "%s\t%s\t%d\t%d\n", r.domain, r.page, r.visits, r.uniques) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user