+void EventsModel::set_formation_at(uint64_t t, bool offense, unsigned formation)
+{
+ // If there's another goal/stoppage/turnover no more than 20 seconds ago,
+ // we assume that the formation started at that point (it just took
+ // the operator a bit of time to see it). If not, we assume we
+ // changed in the middle of a point.
+ uint64_t backdate_point = 0;
+ for (const Event &e : events) {
+ if (e.t > t) {
+ break;
+ }
+ if (e.type == "goal" || e.type == "their_goal" ||
+ e.type == "in" || e.type == "out" ||
+ e.type == "stoppage" || e.type == "reset" ||
+ e.type == "set_defense" || e.type == "set_offense" ||
+ e.type == "throwaway" || e.type == "their_throwaway" ||
+ e.type == "drop" || e.type == "was_d" || e.type == "defense" || e.type == "interception" || e.type == "stallout" ||
+ e.type == "pull" || e.type == "pull_landed" || e.type == "pull_oob" || e.type == "their_pull" ||
+ e.type == "formation_offense" || e.type == "formation_defense") {
+ backdate_point = e.t + 1;
+ }
+ if (e.type == "formation_offense" || e.type == "formation_defense") {
+ backdate_point = 0;
+ }
+ }
+ if (backdate_point != 0 && t - backdate_point < 20000) {
+ t = backdate_point;
+ }
+ if (offense) {
+ insert_event(t, nullopt, formation == 0 ? nullopt : optional{formation}, "formation_offense");
+ } else {
+ insert_event(t, nullopt, formation == 0 ? nullopt : optional{formation}, "formation_defense");
+ }
+}
+