+
+void EventsModel::set_formation_at(uint64_t t, bool offense, unsigned formation)
+{
+ // If there's another goal/stoppage 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 == "stoppage" || e.type == "reset" || e.type == "set_offense" || e.type == "set_defense" || e.type == "in" || e.type == "out" || e.type == "pull" || e.type == "their_pull") {
+ 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");
+ }
+}
+
+vector<int> EventsModel::sort_team(const set<int> &team) const
+{
+ vector<int> ret(team.begin(), team.end());
+ std::sort(ret.begin(), ret.end(), [this](int a, int b) {
+ return player_ordering.find(a)->second < player_ordering.find(b)->second;
+ });
+ return ret;
+}