87 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			87 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|   | // 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 report | ||
|  | 
 | ||
|  | import ( | ||
|  | 	"sort" | ||
|  | ) | ||
|  | 
 | ||
|  | // Summary aggregates the parsing results | ||
|  | type Summary struct { | ||
|  | 	sum     map[string]Result // metrics per domain | ||
|  | 	domains []string          // unique domain names | ||
|  | 	total   Result            // total visits for all domains | ||
|  | } | ||
|  | 
 | ||
|  | // newSummary constructs and initializes a new summary | ||
|  | // You can't use its methods without pointer mechanics | ||
|  | func newSummary() *Summary { | ||
|  | 	return &Summary{sum: make(map[string]Result)} | ||
|  | } | ||
|  | 
 | ||
|  | // Update updates the report for the given parsing result | ||
|  | func (s *Summary) update(r Result) { | ||
|  | 	domain := r.Domain | ||
|  | 	if _, ok := s.sum[domain]; !ok { | ||
|  | 		s.domains = append(s.domains, domain) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// let the result handle the addition | ||
|  | 	// this allows us to manage the result in once place | ||
|  | 	// and this way it becomes easily extendable | ||
|  | 	s.total = s.total.add(r) | ||
|  | 	s.sum[domain] = r.add(s.sum[domain]) | ||
|  | } | ||
|  | 
 | ||
|  | // Iterator returns `next()` to detect when the iteration ends, | ||
|  | // and a `cur()` to return the current result. | ||
|  | // iterator iterates sorted by domains. | ||
|  | func (s *Summary) Iterator() (next func() bool, cur func() Result) { | ||
|  | 	sort.Strings(s.domains) | ||
|  | 
 | ||
|  | 	// remember the last iterated result | ||
|  | 	var last int | ||
|  | 
 | ||
|  | 	next = func() bool { | ||
|  | 		defer func() { last++ }() | ||
|  | 		return len(s.domains) > last | ||
|  | 	} | ||
|  | 
 | ||
|  | 	cur = func() Result { | ||
|  | 		// returns a copy so the caller cannot change it | ||
|  | 		name := s.domains[last-1] | ||
|  | 		return s.sum[name] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return | ||
|  | } | ||
|  | 
 | ||
|  | // Total returns the total metrics | ||
|  | func (s *Summary) Total() Result { | ||
|  | 	return s.total | ||
|  | } | ||
|  | 
 | ||
|  | // For the interfaces section | ||
|  | // | ||
|  | // MarshalJSON marshals a report to JSON | ||
|  | // Alternative: unexported embedding | ||
|  | // func (s *Summary) MarshalJSON() ([]byte, error) { | ||
|  | // 	type total struct { | ||
|  | // 		*Result | ||
|  | // 		IgnoreDomain *string `json:"domain,omitempty"` | ||
|  | // 	} | ||
|  | 
 | ||
|  | // 	return json.Marshal(struct { | ||
|  | // 		Sum     map[string]Result `json:"summary"` | ||
|  | // 		Domains []string          `json:"domains"` | ||
|  | // 		Total   total             `json:"total"` | ||
|  | // 	}{ | ||
|  | // 		Sum: s.sum, Domains: s.domains, Total: total{Result: &s.total}, | ||
|  | // 	}) | ||
|  | // } |