events.go 3.61 KB
Newer Older
1 2
package gui

Loïck Bonniot's avatar
Loïck Bonniot committed
3 4
// This file handles event timers and imports.

5 6 7
import (
	"fmt"
	"math"
Loïck Bonniot's avatar
Loïck Bonniot committed
8
	"time"
9

Loïck Bonniot's avatar
Loïck Bonniot committed
10
	"dfss/dfssd/api"
11
	"github.com/visualfc/goqt/ui"
12 13
)

Loïck Bonniot's avatar
Loïck Bonniot committed
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
// AddEvent interprets an incoming event into a graphic one.
// Expected format:
//
// Timestamp: unix nano timestamp
// Identifier: either "platform", "ttp" or "<email>"
// Log: one of the following
//			"sent promise to <email>"
//      "sent signature to <email>"
//
// Other messages are currently ignored.
func (w *Window) AddEvent(e *api.Log) {
	event := Event{
		Sender: w.scene.identifierToIndex(e.Identifier),
		Date:   time.Unix(0, e.Timestamp),
	}

	w.Log(fmt.Sprint(e.Identifier, " ", e.Log))

	var receiver string
	if n, _ := fmt.Sscanf(e.Log, "sent promise to %s", &receiver); n > 0 {
		event.Type = PROMISE
		event.Receiver = w.scene.identifierToIndex(receiver)
	} else if n, _ := fmt.Sscanf(e.Log, "sent signature to %s", &receiver); n > 0 {
		event.Type = SIGNATURE
		event.Receiver = w.scene.identifierToIndex(receiver)
	}

	if receiver != "" {
		w.scene.Events = append(w.scene.Events, event)
	}
}
45

Loïck Bonniot's avatar
Loïck Bonniot committed
46
// DrawEvent triggers the appropriate draw action for a spectific event.
47 48 49
func (w *Window) DrawEvent(e *Event) {
	xa, ya := w.GetClientPosition(e.Sender)
	xb, yb := w.GetClientPosition(e.Receiver)
Loïck Bonniot's avatar
Loïck Bonniot committed
50 51 52 53 54 55 56 57 58 59 60 61

	var color string
	switch e.Type {
	case PROMISE:
		color = "blue"
	case SIGNATURE:
		color = "green"
	default:
		color = "black"
	}

	w.DrawArrow(xa, ya, xb, yb, colors[color])
62 63
}

Loïck Bonniot's avatar
Loïck Bonniot committed
64
// PrintQuantumInformation triggers the update of the "x / y" quantum information.
65
func (w *Window) PrintQuantumInformation() {
66 67 68 69 70
	if len(w.scene.Events) == 0 {
		w.progress.SetText("No event")
		return
	}

71 72
	quantum := float64(w.quantumField.Value())

73
	beginning := w.scene.Events[0].Date.UnixNano()
Loïck Bonniot's avatar
Loïck Bonniot committed
74
	totalDuration := w.scene.Events[len(w.scene.Events)-1].Date.UnixNano() - beginning
75
	nbQuantum := math.Floor(float64(totalDuration)/quantum) + 1
76
	durationFromBeginning := w.scene.currentTime.UnixNano() - beginning
Loïck Bonniot's avatar
Loïck Bonniot committed
77
	currentQuantum := math.Ceil(float64(durationFromBeginning)/quantum) + 1
78

79 80 81
	if w.scene.currentEvent == 0 {
		currentQuantum = 0
	}
82 83 84
	w.progress.SetText(fmt.Sprint(currentQuantum, " / ", nbQuantum))
}

Loïck Bonniot's avatar
Loïck Bonniot committed
85
// initTimer is called during window initialization. It initializes the timeout signal called for each refresh.
86 87
func (w *Window) initTimer() {
	w.timer = ui.NewTimerWithParent(w)
Loïck Bonniot's avatar
Loïck Bonniot committed
88 89 90

	lastNbOfClients := len(w.scene.Clients)

91
	w.timer.OnTimeout(func() {
92 93
		nbEvents := len(w.scene.Events)
		if w.scene.currentEvent >= nbEvents {
94 95
			w.replayButton.Click()
			return
96 97 98 99 100 101 102
		}

		// Remove arrows from last tick
		w.RemoveArrows()

		// Check that we have a least one event to read
		if nbEvents == 0 {
103
			return
104 105
		}

Loïck Bonniot's avatar
Loïck Bonniot committed
106 107 108 109 110
		// Check if need to redraw everything
		if lastNbOfClients != len(w.scene.Clients) {
			w.initScene()
		}

111 112 113 114 115
		// Init first time
		if w.scene.currentEvent == 0 {
			w.scene.currentTime = w.scene.Events[0].Date
		}

116
		quantum := time.Duration(w.quantumField.Value())
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
		endOfQuantum := w.scene.currentTime.Add(quantum * time.Nanosecond)

		for i := w.scene.currentEvent; i < nbEvents; i++ {
			e := w.scene.Events[i]

			if e.Date.After(endOfQuantum) || e.Date.Equal(endOfQuantum) {
				break
			}

			w.DrawEvent(&e)
			w.scene.currentEvent++
		}

		w.PrintQuantumInformation()
		w.scene.currentTime = endOfQuantum
132
	})
133
}
Loïck Bonniot's avatar
Loïck Bonniot committed
134

Loïck Bonniot's avatar
Loïck Bonniot committed
135
// identifierToIndex is used to retrieve a client index from its name, inserting a new client if needed.
Loïck Bonniot's avatar
Loïck Bonniot committed
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
func (s *Scene) identifierToIndex(identifier string) int {
	if identifier == "platform" {
		return -1
	}
	if identifier == "ttp" {
		return -2
	}

	for i, c := range s.Clients {
		if c.Name == identifier {
			return i
		}
	}

	s.Clients = append(s.Clients, Client{Name: identifier})
	return len(s.Clients) - 1
}