| 
									
										
										
										
											2019-08-17 15:55:25 +03:00
										 |  |  | // Copyright © 2018 Inanc Gumus | 
					
						
							|  |  |  | // Learn Go Programming Course | 
					
						
							|  |  |  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2019-10-30 19:34:44 +03:00
										 |  |  | // For more tutorials  : https://learngoprogramming.com | 
					
						
							|  |  |  | // In-person training  : https://www.linkedin.com/in/inancgumus/ | 
					
						
							|  |  |  | // Follow me on twitter: https://twitter.com/inancgumus | 
					
						
							| 
									
										
										
										
											2019-08-17 15:55:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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}, | 
					
						
							|  |  |  | // 	}) | 
					
						
							|  |  |  | // } |