Exemplo n.º 1
0
func process(doneTime time.Time, r io.Reader, a *accounting, resultChan chan result) {
	defer close(resultChan)

	tr := newTruckReader(r)
	in := make(chan *truck)
	out := make(chan *truck)

	// Construct the repacker.
	newRepacker(in, out)

	// A goroutine to read and send trucks
	go func() {
		defer close(in)

		for {
			done := time.Now().After(doneTime)

			t, err := tr.Next()
			if done || err != nil {
				if done {
					fmt.Println("timeout")
				}

				if err != nil && err != io.EOF {
					fmt.Println("truck reading error: ", err)
				}

				// Send one more empty truck as a signal that they now
				// need to send out any stored boxes.
				a.trucksMu.Lock()
				a.trucks[idLastTruck] = 0
				a.trucksMu.Unlock()
				in <- &truck{id: idLastTruck}

				return
			}

			a.boxesMu.Lock()
			for _, p := range t.pallets {
				for _, b := range p.boxes {
					a.boxes[b.canon()] = true
				}
			}
			a.boxesMu.Unlock()

			// Remember how many pallets were in the truck.
			a.trucksMu.Lock()
			a.trucks[t.id] = len(t.pallets)
			a.trucksMu.Unlock()

			in <- t
		}
	}()

	// Receive the trucks and check them.
	for t := range out {
		r := result{}
		totalUtilization := float64(0)
		palletCount := 0
		// Only correctly packed pallets count
		for pn, p := range t.pallets {
			palletCount++
			for _, b := range p.boxes {
				if !a.boxOk(b) {
					log.Printf("box %v in truck %d was not in the input", b.id, t.id)
					r.fail = true
				}
			}
			if err := p.IsValid(); err == nil {
				r.items += p.Items()
				totalUtilization += p.Utilization()
			} else {
				log.Printf("pallet %v in truck %d is not correctly packed: %v", pn, t.id, err)
				r.fail = true
			}
		}

		// Calculate the profit (or loss!) of pallets.
		a.trucksMu.Lock()
		if _, ok := a.trucks[t.id]; ok {
			r.profit = a.trucks[t.id] - len(t.pallets)
		} else {
			log.Printf("truck %v unknown", t.id)
			r.fail = true
		}
		a.trucksMu.Unlock()

		r.palletUtilization = totalUtilization / float64(palletCount)
		resultChan <- r
	}

	a.boxesMu.Lock()
	if len(a.boxes) != 0 {
		log.Printf("%v boxes not seen in the departing trucks", len(a.boxes))
		resultChan <- result{fail: true}
	}
	a.boxesMu.Unlock()
}