Commit f2c44b6c authored by Loïck Bonniot's avatar Loïck Bonniot
Browse files

[d] Improve event import

parent 1f645003
Pipeline #503 failed with stage
...@@ -4,8 +4,8 @@ import "github.com/visualfc/goqt/ui" ...@@ -4,8 +4,8 @@ import "github.com/visualfc/goqt/ui"
var colors = map[string]uint32{ var colors = map[string]uint32{
"red": 0x00ff0000, "red": 0x00ff0000,
"blue": 0x0000ff00, "green": 0x0000aa00,
"green": 0x000000ff, "blue": 0x000000ff,
"black": 0x00000000, "black": 0x00000000,
} }
......
...@@ -2,20 +2,64 @@ package gui ...@@ -2,20 +2,64 @@ package gui
import ( import (
"fmt" "fmt"
"time"
"math" "math"
"time"
"dfss/dfssd/api"
"github.com/visualfc/goqt/ui" "github.com/visualfc/goqt/ui"
) )
// TEMPORARY // TEMPORARY
const quantum = 100 // discretization argument for events (ns) const quantum = 100 // discretization argument for events (ns)
const speed = 500 // duration of a quantum (ms) const speed = 1000 // duration of a quantum (ms)
// 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)
}
}
func (w *Window) DrawEvent(e *Event) { func (w *Window) DrawEvent(e *Event) {
xa, ya := w.GetClientPosition(e.Sender) xa, ya := w.GetClientPosition(e.Sender)
xb, yb := w.GetClientPosition(e.Receiver) xb, yb := w.GetClientPosition(e.Receiver)
w.DrawArrow(xa, ya, xb, yb, colors["red"])
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])
} }
func (w *Window) PrintQuantumInformation() { func (w *Window) PrintQuantumInformation() {
...@@ -25,10 +69,10 @@ func (w *Window) PrintQuantumInformation() { ...@@ -25,10 +69,10 @@ func (w *Window) PrintQuantumInformation() {
} }
beginning := w.scene.Events[0].Date.UnixNano() beginning := w.scene.Events[0].Date.UnixNano()
totalDuration := w.scene.Events[len(w.scene.Events) - 1].Date.UnixNano() - beginning totalDuration := w.scene.Events[len(w.scene.Events)-1].Date.UnixNano() - beginning
nbQuantum := math.Ceil(float64(totalDuration) / quantum) nbQuantum := math.Max(1, math.Ceil(float64(totalDuration)/quantum))
durationFromBeginning := w.scene.currentTime.UnixNano() - beginning durationFromBeginning := w.scene.currentTime.UnixNano() - beginning
currentQuantum := math.Ceil(float64(durationFromBeginning) / quantum)+1 currentQuantum := math.Ceil(float64(durationFromBeginning)/quantum) + 1
if w.scene.currentEvent == 0 { if w.scene.currentEvent == 0 {
currentQuantum = 0 currentQuantum = 0
...@@ -38,6 +82,9 @@ func (w *Window) PrintQuantumInformation() { ...@@ -38,6 +82,9 @@ func (w *Window) PrintQuantumInformation() {
func (w *Window) initTimer() { func (w *Window) initTimer() {
w.timer = ui.NewTimerWithParent(w) w.timer = ui.NewTimerWithParent(w)
lastNbOfClients := len(w.scene.Clients)
w.timer.OnTimeout(func() { w.timer.OnTimeout(func() {
nbEvents := len(w.scene.Events) nbEvents := len(w.scene.Events)
if w.scene.currentEvent >= nbEvents { if w.scene.currentEvent >= nbEvents {
...@@ -53,6 +100,11 @@ func (w *Window) initTimer() { ...@@ -53,6 +100,11 @@ func (w *Window) initTimer() {
return return
} }
// Check if need to redraw everything
if lastNbOfClients != len(w.scene.Clients) {
w.initScene()
}
// Init first time // Init first time
if w.scene.currentEvent == 0 { if w.scene.currentEvent == 0 {
w.scene.currentTime = w.scene.Events[0].Date w.scene.currentTime = w.scene.Events[0].Date
...@@ -75,3 +127,21 @@ func (w *Window) initTimer() { ...@@ -75,3 +127,21 @@ func (w *Window) initTimer() {
w.scene.currentTime = endOfQuantum w.scene.currentTime = endOfQuantum
}) })
} }
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
}
...@@ -26,6 +26,10 @@ func (w *Window) DrawClients() { ...@@ -26,6 +26,10 @@ func (w *Window) DrawClients() {
} }
func (w *Window) GetClientPosition(i int) (x, y float64) { func (w *Window) GetClientPosition(i int) (x, y float64) {
if i < 0 {
return w.GetServerPosition(i == -1)
}
nbClients := float64(len(w.scene.Clients)) nbClients := float64(len(w.scene.Clients))
angle := 2 * math.Pi * float64(i) / nbClients angle := 2 * math.Pi * float64(i) / nbClients
return math.Cos(angle) * (w.circleSize / 2), math.Sin(angle) * (w.circleSize / 2) return math.Cos(angle) * (w.circleSize / 2), math.Sin(angle) * (w.circleSize / 2)
...@@ -33,7 +37,7 @@ func (w *Window) GetClientPosition(i int) (x, y float64) { ...@@ -33,7 +37,7 @@ func (w *Window) GetClientPosition(i int) (x, y float64) {
func (w *Window) GetServerPosition(platform bool) (x, y float64) { func (w *Window) GetServerPosition(platform bool) (x, y float64) {
x = w.circleSize/2 + 150 x = w.circleSize/2 + 150
y = -16 y = 0
if !platform { if !platform {
x *= -1 x *= -1
} }
...@@ -45,12 +49,12 @@ func (w *Window) DrawServers() { ...@@ -45,12 +49,12 @@ func (w *Window) DrawServers() {
ttp := scene.AddPixmap(w.pixmaps["ttp"]) ttp := scene.AddPixmap(w.pixmaps["ttp"])
x, y := w.GetServerPosition(false) x, y := w.GetServerPosition(false)
ttp.SetPosFWithXY(x, y) ttp.SetPosFWithXY(x-32, y-16)
ttp.SetToolTip("TTP") ttp.SetToolTip("TTP")
platform := scene.AddPixmap(w.pixmaps["platform"]) platform := scene.AddPixmap(w.pixmaps["platform"])
platform.SetX(w.circleSize/2 + 150) x, y = w.GetServerPosition(true)
platform.SetY(-16) platform.SetPosFWithXY(x, y-16)
platform.SetToolTip("Platform") platform.SetToolTip("Platform")
} }
......
...@@ -12,15 +12,15 @@ import ( ...@@ -12,15 +12,15 @@ import (
type Window struct { type Window struct {
*ui.QMainWindow *ui.QMainWindow
logField *ui.QTextEdit logField *ui.QTextEdit
graphics *ui.QGraphicsView graphics *ui.QGraphicsView
progress *ui.QLabel progress *ui.QLabel
playButton *ui.QPushButton playButton *ui.QPushButton
stopButton *ui.QPushButton stopButton *ui.QPushButton
replayButton *ui.QPushButton replayButton *ui.QPushButton
scene *Scene scene *Scene
circleSize float64 circleSize float64
pixmaps map[string]*ui.QPixmap pixmaps map[string]*ui.QPixmap
currentArrows []*ui.QGraphicsPathItem currentArrows []*ui.QGraphicsPathItem
timer *ui.QTimer timer *ui.QTimer
...@@ -53,6 +53,6 @@ type Scene struct { ...@@ -53,6 +53,6 @@ type Scene struct {
Clients []Client Clients []Client
Events []Event Events []Event
currentTime time.Time currentTime time.Time
currentEvent int currentEvent int
} }
...@@ -47,19 +47,6 @@ func NewWindow() *Window { ...@@ -47,19 +47,6 @@ func NewWindow() *Window {
w.initScene() w.initScene()
w.initTimer() w.initTimer()
// TEST ONLY
w.scene.Clients = []Client{
Client{"signer1@lesterpig.com"},
Client{"signer2@insa-rennes.fr"},
Client{"signer3@dfss.com"},
}
w.scene.Events = []Event{
Event{PROMISE, 0, 1, time.Unix(0, 5)},
Event{SIGNATURE, 1, 2, time.Unix(0, 15)},
Event{PROMISE, 1, 0, time.Unix(0, 134)},
Event{OTHER, 0, 1, time.Unix(0, 402)},
}
w.StatusBar().ShowMessage("Ready") w.StatusBar().ShowMessage("Ready")
w.PrintQuantumInformation() w.PrintQuantumInformation()
return w return w
...@@ -71,6 +58,7 @@ func (w *Window) OnResizeEvent(ev *ui.QResizeEvent) bool { ...@@ -71,6 +58,7 @@ func (w *Window) OnResizeEvent(ev *ui.QResizeEvent) bool {
} }
func (w *Window) Log(str string) { func (w *Window) Log(str string) {
str = time.Now().Format("[15:04:05.000] ") + str
w.logField.Append(str) w.logField.Append(str)
w.logField.EnsureCursorVisible() w.logField.EnsureCursorVisible()
} }
...@@ -120,15 +108,13 @@ func (w *Window) addActions() { ...@@ -120,15 +108,13 @@ func (w *Window) addActions() {
w.playButton.OnClicked(func() { w.playButton.OnClicked(func() {
w.playButton.SetDisabled(true) w.playButton.SetDisabled(true)
w.stopButton.SetDisabled(false) w.stopButton.SetDisabled(false)
w.timer.StartWithMsec(500) w.timer.StartWithMsec(speed)
w.Log("Started simulation")
}) })
w.stopButton.OnClicked(func() { w.stopButton.OnClicked(func() {
w.playButton.SetDisabled(false) w.playButton.SetDisabled(false)
w.stopButton.SetDisabled(true) w.stopButton.SetDisabled(true)
w.timer.Stop() w.timer.Stop()
w.Log("Paused simulation")
}) })
w.stopButton.SetDisabled(true) w.stopButton.SetDisabled(true)
...@@ -136,7 +122,6 @@ func (w *Window) addActions() { ...@@ -136,7 +122,6 @@ func (w *Window) addActions() {
w.RemoveArrows() w.RemoveArrows()
w.scene.currentEvent = 0 w.scene.currentEvent = 0
w.PrintQuantumInformation() w.PrintQuantumInformation()
w.Log("Restarting simulation")
}) })
} }
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"strconv" "strconv"
"dfss" "dfss"
"dfss/dfssd/api"
"dfss/dfssd/gui" "dfss/dfssd/gui"
"dfss/dfssd/server" "dfss/dfssd/server"
"github.com/visualfc/goqt/ui" "github.com/visualfc/goqt/ui"
...@@ -51,10 +52,10 @@ func main() { ...@@ -51,10 +52,10 @@ func main() {
case "version": case "version":
fmt.Println("v"+dfss.Version, runtime.GOOS, runtime.GOARCH) fmt.Println("v"+dfss.Version, runtime.GOOS, runtime.GOARCH)
case "nogui": case "nogui":
lfn := func(str string) { fn := func(v *api.Log) {
fmt.Println(str) fmt.Printf("[%d] %s: %s\n", v.Timestamp, v.Identifier, v.Log)
} }
err := server.Listen("0.0.0.0:"+strconv.Itoa(port), lfn) err := server.Listen("0.0.0.0:"+strconv.Itoa(port), fn)
if err != nil { if err != nil {
os.Exit(1) os.Exit(1)
} }
...@@ -62,7 +63,7 @@ func main() { ...@@ -62,7 +63,7 @@ func main() {
ui.Run(func() { ui.Run(func() {
window := gui.NewWindow() window := gui.NewWindow()
go func() { go func() {
err := server.Listen("0.0.0.0:"+strconv.Itoa(port), window.Log) err := server.Listen("0.0.0.0:"+strconv.Itoa(port), window.AddEvent)
if err != nil { if err != nil {
window.Log("!! " + err.Error()) window.Log("!! " + err.Error())
} }
......
...@@ -20,17 +20,16 @@ func (s *Server) SendLog(ctx context.Context, in *api.Log) (*api.Ack, error) { ...@@ -20,17 +20,16 @@ func (s *Server) SendLog(ctx context.Context, in *api.Log) (*api.Ack, error) {
} }
// Listen with gRPG service // Listen with gRPG service
func Listen(addrPort string, lfn func(string)) error { func Listen(addrPort string, fn func(*api.Log)) error {
// open tcp socket // open tcp socket
lis, err := net.Listen("tcp", addrPort) lis, err := net.Listen("tcp", addrPort)
if err != nil { if err != nil {
grpclog.Fatalf("Failed to open tcp socket: %v", err) grpclog.Fatalf("Failed to open tcp socket: %v", err)
return err return err
} }
lfn("Server listening on " + addrPort)
// log display manager // log display manager
go displayHandler(lfn) go displayHandler(fn)
// bootstrap gRPC service ! // bootstrap gRPC service !
grpcServer := grpc.NewServer() grpcServer := grpc.NewServer()
......
package server package server
import ( import (
"fmt"
"sort" "sort"
"sync" "sync"
"time" "time"
...@@ -23,7 +22,7 @@ func addMessage(msg *api.Log) { ...@@ -23,7 +22,7 @@ func addMessage(msg *api.Log) {
} }
// display logs that are more than since (ms) old // display logs that are more than since (ms) old
func display(since int64, lfn func(string)) { func display(since int64, fn func(*api.Log)) {
var out []*api.Log // sorted messages to display var out []*api.Log // sorted messages to display
var recycled []*api.Log // messages too recent to be displayed var recycled []*api.Log // messages too recent to be displayed
...@@ -45,15 +44,16 @@ func display(since int64, lfn func(string)) { ...@@ -45,15 +44,16 @@ func display(since int64, lfn func(string)) {
sort.Sort(ByTimestamp(out)) sort.Sort(ByTimestamp(out))
for _, v := range out { for _, v := range out {
lfn(fmt.Sprintf("[%d] %s:: %s", v.Timestamp, v.Identifier, v.Log)) //lfn()
fn(v)
} }
} }
// refresh every second // refresh every second
func displayHandler(lfn func(string)) { func displayHandler(fn func(*api.Log)) {
ticker := time.NewTicker(time.Second) ticker := time.NewTicker(time.Second)
for range ticker.C { for range ticker.C {
display(1000, lfn) display(1000, fn)
} }
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment