diff --git a/game/foul.go b/game/foul.go
index fe28ca2..10c9b9d 100644
--- a/game/foul.go
+++ b/game/foul.go
@@ -18,7 +18,7 @@ func (foul *Foul) Rule() *Rule {
// Returns the number of points that the foul adds to the opposing alliance's score.
func (foul *Foul) PointValue() int {
- if foul.Rule() == nil {
+ if foul.Rule() == nil || foul.Rule().IsRankingPoint {
return 0
}
if foul.Rule().IsTechnical {
diff --git a/game/rule.go b/game/rule.go
index 7ef608b..37e8365 100644
--- a/game/rule.go
+++ b/game/rule.go
@@ -13,35 +13,42 @@ type Rule struct {
Description string
}
-// All rules from the 2018 game that carry point penalties.
+// All rules from the 2020 game that carry point penalties.
var rules = []*Rule{
- {1, "S6", false, false, "DRIVE TEAMS may not extend any body part into the CARGO Chute. Momentary encroachment into the Chute is an exception to this rule."},
+ {1, "S6", false, false, "DRIVE TEAMS may not extend any body part into the LOADING BAY Chute."},
{2, "C8", false, false, "Strategies clearly aimed at forcing the opposing ALLIANCE to violate a rule are not in the spirit of FIRST Robotics Competition and not allowed."},
- {3, "G3", true, false, "During the SANDSTORM PERIOD, a ROBOT may not cross the FIELD such that its BUMPERS break the plane defined by their opponent’s CARGO SHIP LINE."},
- {4, "G4", false, false, "ROBOTS may not have greater-than-momentary or repeated control, i.e. exercise greater-than-momentary or repeated influence, of more than one (1) GAME PIECE at a time, either directly or transitively through other objects."},
- {5, "G5", false, true, "A ROBOT may not remove a GAME PIECE from an opponents’ ROCKET/CARGO SHIP."},
- {6, "G7", false, false, "ROBOTS may not intentionally eject GAME PIECES from the FIELD."},
- {7, "G8", false, false, "ROBOTS may not deliberately use GAME PIECES in an attempt to ease or amplify the challenge associated with FIELD elements."},
- {8, "G9", false, false, "No more than one ROBOT may be positioned such that its BUMPERS are completely beyond the opponent’s CARGO SHIP LINE."},
- {9, "G9", true, false, "No more than one ROBOT may be positioned such that its BUMPERS are completely beyond the opponent’s CARGO SHIP LINE."},
- {10, "G10", false, false, "No part of a ROBOT, except its BUMPERS, may be outside its FRAME PERIMETER if its BUMPERS are completely beyond its opponent’s CARGO SHIP LINE."},
- {11, "G10", true, false, "No part of a ROBOT, except its BUMPERS, may be outside its FRAME PERIMETER if its BUMPERS are completely beyond its opponent’s CARGO SHIP LINE."},
- {12, "G12", false, false, "A ROBOT may not break the vertical plane above the ALLIANCE STATION WALL or damage the SANDSTORM."},
- {13, "G13", false, false, "A ROBOT may not contact an opponent ROBOT if that opponent ROBOT’S BUMPERS are fully in their HAB ZONE."},
- {14, "G15", false, false, "DRIVE TEAMS, ROBOTS, and OPERATOR CONSOLES are prohibited from the following actions with regards to interaction with ARENA elements: grabbing, grasping, attaching to, hanging, deforming, becoming entangled, damaging, and repositioning GAME PIECE holders."},
- {15, "G16", false, true, "During Qualification MATCHES, ROBOTS may not contact opponents’ ROCKETS starting at T-minus 20s."},
- {16, "G17", false, false, "Fallen (i.e. tipped over) ROBOTS attempting to right themselves (either by themselves or with assistance from a partner ROBOT) have one ten (10) second grace period in which they may not be contacted by an opponent ROBOT."},
- {17, "G18", false, false, "ROBOTS may not pin an opponent’s ROBOT for more than five (5) seconds."},
- {18, "G18", true, false, "ROBOTS may not pin an opponent’s ROBOT for more than five (5) seconds."},
- {19, "G19", true, false, "Strategies aimed at the destruction or inhibition of ROBOTS via attachment, damage, tipping, or entanglements are not allowed."},
- {20, "G20", true, false, "Initiating deliberate or damaging contact with an opponent ROBOT on or inside the vertical extension of its FRAME PERIMETER, including transitively through a GAME PIECE, is not allowed."},
- {21, "G23", false, false, "BUMPERS must be in the BUMPER ZONE during the MATCH unless a ROBOT is completely in its HAB ZONE or supported by a ROBOT completely in its HAB ZONE."},
- {22, "G24", false, false, "ROBOTS may not extend more than 30 in (~76 cm). beyond their FRAME PERIMETER."},
- {23, "H6", false, false, "During the MATCH, DRIVERS, COACHES, and HUMAN PLAYERS may not contact anything outside the ALLIANCE STATION and TECHNICIANS may not contact anything outside their designated area."},
- {24, "H7", false, false, "During the MATCH, team members may only enter GAME PIECES on to the FIELD through their LOADING STATIONS."},
- {25, "H8", false, false, "During a MATCH, COACHES may not touch GAME PIECES unless for safety purposes."},
- {26, "H9", true, false, "During the SANDSTORM PERIOD, COACHES, DRIVERS, HUMAN PLAYERS, and any part of the OPERATOR CONSOLE may not break the vertical planes defined by the STARTING LINES, unless for safety purposes."},
- {27, "H10", true, false, "During the SANDSTORM PERIOD, COACHES, DRIVERS, and HUMAN PLAYERS may not look over the top of the ALLIANCE WALL down to the FIELD to overcome the effect of the SANDSTORM."},
+ {3, "C8", true, false, "Strategies clearly aimed at forcing the opposing ALLIANCE to violate a rule are not in the spirit of FIRST Robotics Competition and not allowed."},
+ {4, "G3", false, false, "During AUTO, a ROBOT’s BUMPERS may not break the plane of their ALLIANCE’s SECTOR."},
+ {5, "G3", true, false, "During AUTO, a ROBOT’s BUMPERS may not break the plane of their ALLIANCE’s SECTOR."},
+ {6, "G4", false, false, "During AUTO, DRIVE TEAM members in ALLIANCE STATIONS may not contact anything in front of the STARTING LINES, unless for personal or equipment safety."},
+ {7, "G5", false, false, "During AUTO, DRIVE TEAMS may not directly or indirectly interact with ROBOTS or OPERATOR CONSOLES unless for personal safety, OPERATOR CONSOLE safety, or pressing an E-Stop."},
+ {8, "G6", false, false, "ROBOTS may not have greater-than-momentary CONTROL of more than five (5) POWER CELLS at a time, either directly or transitively through other objects."},
+ {9, "G7", false, false, "ROBOTS may not intentionally eject POWER CELLS from the FIELD other than through the POWER PORT."},
+ {10, "G8", true, false, "ROBOTS may not deliberately use POWER CELLS in an attempt to ease or amplify the challenge associated with FIELD elements."},
+ {11, "G9", true, false, "A ROBOT whose BUMPERS are fully contained by their SECTOR may not cause POWER CELLS to travel into or through their opponent’s SECTOR."},
+ {12, "G10", true, false, "A ROBOT whose BUMPERS are intersecting the opponent’s TARGET ZONE, TRENCH RUN, or LOADING ZONE may not contact opponent ROBOTS, regardless of who initiates contact."},
+ {13, "G11", true, false, "An opponent ROBOT may not contact a ROBOT whose BUMPERS are intersecting its TARGET ZONE or LOADING ZONE, regardless of who initiates contact."},
+ {14, "G12", false, true, "A ROBOT may not contact the opponent’s CONTROL PANEL, either directly, or transitively through a POWER CELL, if A. the opponent ROBOT is contacting that CONTROL PANEL, and B. the opponent’s POWER PORT has reached CAPACITY."},
+ {15, "G12", true, false, "A ROBOT may not contact the opponent’s CONTROL PANEL, either directly, or transitively through a POWER CELL, if A. the opponent ROBOT is contacting that CONTROL PANEL, and B. the opponent’s POWER PORT has reached CAPACITY."},
+ {16, "G13", true, false, "A ROBOT may not be fully supported by a partner ROBOT unless the partner ROBOT’S BUMPERS are intersecting its RENDEZVOUS POINT."},
+ {17, "G14", true, false, "During the ENDGAME, a ROBOT may not contact, either directly or transitively through a POWER CELL, an opponent ROBOT whose BUMPERS are completely contained in its RENDEZVOUS POINT and not in contact with its GENERATOR SWITCH."},
+ {18, "G16", false, false, "BUMPERS must be in the BUMPER ZONE during the MATCH, unless during the ENDGAME and A. a ROBOT’s BUMPERS are intersecting its RENDEZVOUS POINT or B. a ROBOT is supported by a partner ROBOT whose BUMPERS are intersecting its RENDEZVOUS POINT."},
+ {19, "G17", true, false, "ROBOT height, as measured when it’s resting normally on a flat floor, may not exceed 45 in. (~114 cm) above the carpet during the MATCH, with the exception of ROBOTS intersecting their ALLIANCE’S RENDEZVOUS POINT during the ENDGAME."},
+ {20, "G18", false, false, "ROBOTS may not extend more than 12 inches (~30 cm) beyond their FRAME PERIMETER."},
+ {21, "G21", false, false, "ROBOTS may not PIN an opponent’s ROBOT for more than five (5) seconds."},
+ {22, "G21", true, false, "ROBOTS may not PIN an opponent’s ROBOT for more than five (5) seconds."},
+ {23, "G22", true, false, "Two or more ROBOTS that appear to a REFEREE to be working together may not isolate or close off any major component of MATCH play."},
+ {24, "G23", true, false, "ROBOT actions that appear to be deliberate to a REFEREE and that cause damage or inhibition via attaching, tipping, or entangling to an opponent ROBOT are not allowed."},
+ {25, "G24", false, false, "A ROBOT with a COMPONENT(S) outside its FRAME PERIMETER, other than BUMPERS, may not initiate direct contact with an opponent ROBOT inside the vertical projection of its FRAME PERIMETER using that COMPONENT."},
+ {26, "G25", true, false, "Regardless of intent, a ROBOT may not initiate direct contact inside the vertical projection of an opponent ROBOT’S FRAME PERIMETER that damages or functionally impairs the opponent ROBOT."},
+ {27, "G26", true, false, "ROBOTS and OPERATOR CONSOLES are prohibited from the following actions with regards to interaction with ARENA elements: grabbing, grasping, attaching, deforming, becoming entangled, damaging, suspending from."},
+ {28, "H5", false, false, "During the MATCH, DRIVERS, COACHES, and HUMAN PLAYERS may not contact anything outside the ALLIANCE STATION and TECHNICIANS may not contact anything outside their designated area."},
+ {29, "H6", false, false, "POWER CELLS may only be introduced to the FIELD A. during TELEOP, B. by a DRIVER or HUMAN PLAYER, and C. through the LOADING BAY."},
+ {30, "H7", false, false, "During a MATCH, COACHES may not touch POWER CELLS, unless for safety purposes."},
+ {31, "H9", false, false, "During TELEOP, an ALLIANCE may not have more than fifteen (15) POWER CELLS in their ALLIANCE STATION."},
+ {32, "H10", false, false, "POWER CELLS must be stored on the LOADING BAY racks."},
+ {33, "H10", true, false, "POWER CELLS must be stored on the LOADING BAY racks."},
+ {34, "H16", true, false, "DRIVE TEAMS are prohibited from the following actions with regards to interaction with ARENA elements: climbing, hanging, deforming, damaging."},
}
var ruleMap map[int]*Rule
diff --git a/game/score.go b/game/score.go
index b641439..f741bce 100644
--- a/game/score.go
+++ b/game/score.go
@@ -123,6 +123,14 @@ func (score *Score) Summarize(opponentFouls []Foul) *ScoreSummary {
summary.FoulPoints += foul.PointValue()
}
+ // Check for the opponent fouls that automatically trigger a ranking point.
+ for _, foul := range opponentFouls {
+ if foul.Rule() != nil && foul.Rule().IsRankingPoint {
+ summary.ControlPanelRankingPoint = true
+ break
+ }
+ }
+
summary.Score = summary.AutoPoints + summary.TeleopPowerCellPoints + summary.ControlPanelPoints +
summary.EndgamePoints + summary.FoulPoints
diff --git a/game/score_test.go b/game/score_test.go
index c09c47b..f181a36 100644
--- a/game/score_test.go
+++ b/game/score_test.go
@@ -126,6 +126,30 @@ func TestScoreSummaryBoundaryConditions(t *testing.T) {
assert.Equal(t, false, score.Summarize(score.Fouls).EndgameRankingPoint)
}
+func TestScoreSummaryRankingPointFoul(t *testing.T) {
+ fouls := []Foul{{14, 0, 0}}
+ score1 := TestScore1()
+ score2 := TestScore2()
+
+ summary := score1.Summarize([]Foul{})
+ assert.Equal(t, 0, summary.FoulPoints)
+ assert.Equal(t, false, summary.ControlPanelRankingPoint)
+ assert.Equal(t, true, summary.EndgameRankingPoint)
+ summary = score1.Summarize(fouls)
+ assert.Equal(t, 0, summary.FoulPoints)
+ assert.Equal(t, true, summary.ControlPanelRankingPoint)
+ assert.Equal(t, true, summary.EndgameRankingPoint)
+
+ summary = score2.Summarize([]Foul{})
+ assert.Equal(t, 0, summary.FoulPoints)
+ assert.Equal(t, true, summary.ControlPanelRankingPoint)
+ assert.Equal(t, false, summary.EndgameRankingPoint)
+ summary = score2.Summarize(fouls)
+ assert.Equal(t, 0, summary.FoulPoints)
+ assert.Equal(t, true, summary.ControlPanelRankingPoint)
+ assert.Equal(t, false, summary.EndgameRankingPoint)
+}
+
func TestScoreEquals(t *testing.T) {
score1 := TestScore1()
score2 := TestScore1()
diff --git a/game/test_helpers.go b/game/test_helpers.go
index 1170198..febad09 100644
--- a/game/test_helpers.go
+++ b/game/test_helpers.go
@@ -7,9 +7,9 @@ package game
func TestScore1() *Score {
fouls := []Foul{
- {18, 25, 150},
- {20, 1868, 0},
- {21, 25, 25.2},
+ {17, 25, 150},
+ {18, 1868, 0},
+ {19, 25, 25.2},
}
return &Score{
ExitedInitiationLine: [3]bool{true, true, false},
diff --git a/templates/referee_panel.html b/templates/referee_panel.html
index aca0ca8..4ed24d3 100644
--- a/templates/referee_panel.html
+++ b/templates/referee_panel.html
@@ -67,7 +67,11 @@
{{end}}
-
+
Note: Tooltips do not contain the entire text of the rule, and depending on the circumstances the
+ prescribed penalty may not be a foul or tech foul.
+
+ If a rule does not appear here, it is because the penalty is either a yellow/red card or a free score for
+ the opponent, and should be applied directly.