@@ -11,47 +11,99 @@ func (c *GameController) ProcessAutoRefRequests(id string, request refproto.Auto
11
11
defer c .ConnectionMutex .Unlock ()
12
12
log .Printf ("Received request from autoRef '%v': %v" , id , request )
13
13
14
- if request .GameEvent != nil {
15
- details := GameEventDetailsFromProto (* request .GameEvent )
16
- event := Event {GameEvent : & GameEvent {Type : details .EventType (), Details : details }}
17
-
18
- c .Engine .applyGameEventFilters (event .GameEvent )
19
-
20
- if c .Engine .GcState .GameEventBehavior [event .GameEvent .Type ] == GameEventBehaviorMajority {
21
- validUntil := c .Engine .TimeProvider ().Add (c .Config .Game .AutoRefProposalTimeout )
22
- newProposal := GameEventProposal {GameEvent : * event .GameEvent , ProposerId : id , ValidUntil : validUntil }
23
-
24
- eventPresent := false
25
- for _ , proposal := range c .Engine .GcState .GameEventProposals {
26
- if proposal .GameEvent .Type == event .GameEvent .Type && proposal .ProposerId == newProposal .ProposerId {
27
- // update proposal
28
- * proposal = newProposal
29
- eventPresent = true
30
- }
31
- }
32
- if ! eventPresent {
33
- c .Engine .GcState .GameEventProposals = append (c .Engine .GcState .GameEventProposals , & newProposal )
34
- }
35
-
36
- totalProposals := 0
37
- var origins []string
38
- for _ , proposal := range c .Engine .GcState .GameEventProposals {
39
- if proposal .GameEvent .Type == event .GameEvent .Type && proposal .ValidUntil .After (c .Engine .TimeProvider ()) {
40
- totalProposals ++
41
- origins = append (origins , proposal .ProposerId )
42
- }
43
- }
44
-
45
- majority := int (math .Floor (float64 (len (c .AutoRefServer .Clients )) / 2.0 ))
46
- if totalProposals > majority {
47
- event .GameEvent .Origins = origins
48
- c .OnNewEvent (event )
49
- }
50
- } else {
51
- event .GameEvent .Origins = []string {id }
14
+ if request .GameEvent == nil {
15
+ return nil
16
+ }
17
+
18
+ details := GameEventDetailsFromProto (* request .GameEvent )
19
+ event := Event {GameEvent : & GameEvent {Type : details .EventType (), Details : details }}
20
+
21
+ c .Engine .applyGameEventFilters (event .GameEvent )
22
+
23
+ validUntil := c .Engine .TimeProvider ().Add (c .Config .Game .AutoRefProposalTimeout )
24
+ proposal := GameEventProposal {GameEvent : * event .GameEvent , ProposerId : id , ValidUntil : validUntil }
25
+
26
+ if matchingEvent := c .Engine .State .FindMatchingRecentGameEvent (event .GameEvent ); matchingEvent != nil {
27
+ // there was already such a game event recently. Just add the proposer to the existing event.
28
+ matchingEvent .Origins = append (matchingEvent .Origins , id )
29
+ } else if c .Engine .applyMajority (& event ) { // look for a majority
30
+
31
+ if c .Engine .isNewProposal (& proposal ) {
32
+ // the autoRef has not submitted the same event recently, so add it to the proposals - waiting for majority
33
+ c .Engine .GcState .GameEventProposals = append (c .Engine .GcState .GameEventProposals , & proposal )
34
+ }
35
+
36
+ numProposals := c .Engine .numberOfMatchingProposals (event .GameEvent )
37
+ majority := int (math .Floor (float64 (len (c .AutoRefServer .Clients )) / 2.0 ))
38
+ if numProposals > majority {
39
+ // there is a majority for a game event that has not yet been submitted to the GC
40
+ // remove the matching proposals and submit the event to the GC
52
41
c .OnNewEvent (event )
53
42
}
43
+
44
+ } else {
45
+ // game event has not been submitted recently (by any autoRef) and no majority required.
46
+ // Just submit this event
47
+ event .GameEvent .Origins = []string {id }
48
+ c .OnNewEvent (event )
54
49
}
55
50
56
51
return nil
57
52
}
53
+
54
+ func (e * Engine ) numberOfMatchingProposals (event * GameEvent ) (count int ) {
55
+ count = 0
56
+ for _ , proposal := range e .GcState .GameEventProposals {
57
+ if proposal .GameEvent .Type == event .Type && e .proposalValid (proposal ) {
58
+ count ++
59
+ }
60
+ }
61
+ return
62
+ }
63
+
64
+ func (e * Engine ) collectAllMatchingProposals (event * GameEvent ) []* GameEventProposal {
65
+ var proposals []* GameEventProposal
66
+ for _ , proposal := range e .GcState .GameEventProposals {
67
+ if proposal .GameEvent .Type == event .Type {
68
+ proposals = append (proposals , proposal )
69
+ }
70
+ }
71
+ return proposals
72
+ }
73
+
74
+ func (e * Engine ) collectNonMatchingProposals (event * GameEvent ) []* GameEventProposal {
75
+ var proposals []* GameEventProposal
76
+ for _ , proposal := range e .GcState .GameEventProposals {
77
+ if proposal .GameEvent .Type != event .Type {
78
+ proposals = append (proposals , proposal )
79
+ }
80
+ }
81
+ return proposals
82
+ }
83
+
84
+ func collectAllOrigins (proposals []* GameEventProposal ) []string {
85
+ var origins []string
86
+ for _ , proposal := range proposals {
87
+ origins = append (origins , proposal .ProposerId )
88
+ }
89
+ return origins
90
+ }
91
+
92
+ func (e * Engine ) proposalValid (proposal * GameEventProposal ) bool {
93
+ return proposal .ValidUntil .After (e .TimeProvider ())
94
+ }
95
+
96
+ func (e * Engine ) isNewProposal (newProposal * GameEventProposal ) bool {
97
+ for _ , proposal := range e .GcState .GameEventProposals {
98
+ if proposal .GameEvent .Type == newProposal .GameEvent .Type &&
99
+ proposal .ProposerId == newProposal .ProposerId &&
100
+ e .proposalValid (proposal ) {
101
+ return false
102
+ }
103
+ }
104
+ return true
105
+ }
106
+
107
+ func (e * Engine ) applyMajority (event * Event ) bool {
108
+ return e .GcState .GameEventBehavior [event .GameEvent .Type ] == GameEventBehaviorMajority
109
+ }
0 commit comments