Skip to content

Ticker

Der Liveticker ist eine eigene Sektion in diesem Projekt.

Interfaces

Innerhalb des TickerView werden verschiedene Interfaces benötigt, um Daten welche von der API zurückgespielt werden zu klassifizieren. Dabei kann sich der Ticker in verschiedenen Zuständen befinden, welche Auswirkungen auf die Ansicht des Users haben.

LivetickerState

Das Interface LivetickerState beinhaltet zu dem noch mehr Stati in die ein Liveticker sich befinden kann. Je nach Stati werden in der Ticker Ansicht verschiedene Dinge angezeigt.

ts
export const LivetickerState = {
  PRE_GAME: 0,
  FIRST_HALF_RUNNING: 1,
  FIRST_HALF_ENDED: 2,
  SECOND_HALF_RUNNING: 3,
  END: 4,
  SECOND_HALF_ENDED: 5,
  EXTRA_TIME_FIRST_HALF_RUNNING: 6,
  EXTRA_TIME_FIRST_HALF_ENDED: 7,
  EXTRA_TIME_SECOND_HALF_RUNNING: 8,
  EXTRA_TIME_SECOND_HALF_ENDED: 9,
  PENALTY_KICKS: 11,
};
export const LivetickerState = {
  PRE_GAME: 0,
  FIRST_HALF_RUNNING: 1,
  FIRST_HALF_ENDED: 2,
  SECOND_HALF_RUNNING: 3,
  END: 4,
  SECOND_HALF_ENDED: 5,
  EXTRA_TIME_FIRST_HALF_RUNNING: 6,
  EXTRA_TIME_FIRST_HALF_ENDED: 7,
  EXTRA_TIME_SECOND_HALF_RUNNING: 8,
  EXTRA_TIME_SECOND_HALF_ENDED: 9,
  PENALTY_KICKS: 11,
};

LivetickerEvent

Das Interface LivetickerEvent zählt zu den wichtigsten Bestandteil der Ticker Anwendung, dass Interface wird benutzt um die verschiedenen Event´s zu unterscheiden.

ts
export const LivetickerEvent = {
  PRE_MATCH_COMMENT: 20,
  POST_MATCH_COMMENT: 21,
  MIDDLE_MATCH_COMMENT: 22,
  COMMENT: -1,
  GOAL: 8,
  SUBSTITUTION: 9,
  YELLOW_CARD: 5,
  RED_CARD: 6,
  YELLOW_RED_CARD: 7,
  ABORTION: 10,
  KICK_OFF: 1,
  HALF_TIME: 2,
  SECOND_HALF: 3,
  SECOND_HALF_END: 4,
  START_EXTRA_TIME_FIRST_HALF: 13,
  END_EXTRA_TIME_FIRST_HALF: 14,
  START_EXTRA_TIME_SECOND_HALF: 15,
  END_EXTRA_TIME_SECOND_HALF: 16,
  PENALTY_KICKS: 17,
  MATCH_END: 18,
};
export const LivetickerEvent = {
  PRE_MATCH_COMMENT: 20,
  POST_MATCH_COMMENT: 21,
  MIDDLE_MATCH_COMMENT: 22,
  COMMENT: -1,
  GOAL: 8,
  SUBSTITUTION: 9,
  YELLOW_CARD: 5,
  RED_CARD: 6,
  YELLOW_RED_CARD: 7,
  ABORTION: 10,
  KICK_OFF: 1,
  HALF_TIME: 2,
  SECOND_HALF: 3,
  SECOND_HALF_END: 4,
  START_EXTRA_TIME_FIRST_HALF: 13,
  END_EXTRA_TIME_FIRST_HALF: 14,
  START_EXTRA_TIME_SECOND_HALF: 15,
  END_EXTRA_TIME_SECOND_HALF: 16,
  PENALTY_KICKS: 17,
  MATCH_END: 18,
};

TickerInfo

Das Interface TickerInfo beinhaltet den Liveticker mit dem Spiel und ein paar grundlegenden Informationen.

ts
export interface TickerInfo {
  id: number;
  fkMatch: number;
  description: string;
  live_goals: string;
  teams_short: string;
  matchDate: Date;
  state: number;
  user: User;
  league: League;
  match: Match;
  liveticker: Liveticker | undefined;
  isCup: boolean | undefined;
};
export interface TickerInfo {
  id: number;
  fkMatch: number;
  description: string;
  live_goals: string;
  teams_short: string;
  matchDate: Date;
  state: number;
  user: User;
  league: League;
  match: Match;
  liveticker: Liveticker | undefined;
  isCup: boolean | undefined;
};

Bevor Anpfiff

Bevor dem Start eines Spiels kann der User schon einiges eintragen, um seinen Leser die Aufstellungen und die Spielstätte/Schiedsrichter mitzuteilen. Dies geschieht über das LineupModal oder mit dem EventModal.

Spielzeit

Die Spielzeit ist der Zustand in dem das Spiel läuft. Hierzu zählt die erste Halbzeit, zweite Halbzeit, erste und zweite Halbzeit der Verlängerung bei einem Spiel, wo dies möglich ist. In halb der Zeit in dem sich der Ticker in einem dieser Zustände befindet können verschidene Event´s angelegt werden.

ts
livetickerState() {
    if (ticker_info.state == LivetickerState.FIRST_HALF_RUNNING 
        || ticker_info.state == LivetickerState.SECOND_HALF_RUNNING 
        || ticker_info.state == LivetickerState.EXTRA_TIME_FIRST_HALF_RUNNING 
        || ticker_info.state == LivetickerState.EXTRA_TIME_SECOND_HALF_RUNNING) {
        return "Anlegen von Event´s ist möglich";
    } else {
        return "Kein anlegen von Ticker Event´s (Tore, Karten)";
    }
}
livetickerState() {
    if (ticker_info.state == LivetickerState.FIRST_HALF_RUNNING 
        || ticker_info.state == LivetickerState.SECOND_HALF_RUNNING 
        || ticker_info.state == LivetickerState.EXTRA_TIME_FIRST_HALF_RUNNING 
        || ticker_info.state == LivetickerState.EXTRA_TIME_SECOND_HALF_RUNNING) {
        return "Anlegen von Event´s ist möglich";
    } else {
        return "Kein anlegen von Ticker Event´s (Tore, Karten)";
    }
}

Zu dem läuft während der Ticker sich in diesen Zuständen befindet ein Timer, welcher benötigt wird bei Anlegen von Event´s und um die Zeit darzustelllen. Dies geschieht mit einer computed Property, diese sieht wie folgt aus.

ts
// Referenz Objekt/Wert
let elapsed_match_seconds: Ref<number | undefined> = ref();

// Ausrechnen der Minute in der sich der Liveticker befindet.
let elapsedMinutes: ComputedRef<number | string> = computed(() => {
  var seconds: number = 0;
  var minutes: number = 0;
  if (
    elapsed_match_seconds.value !== undefined &&
    elapsed_match_seconds.value > 0
  ) {
    seconds = elapsed_match_seconds.value % 60;
    minutes = elapsed_match_seconds.value / 60;
  } else {
    return "Anpfiff";
  }
  if (ticker_info.value?.state == LivetickerState.FIRST_HALF_ENDED) {
    return "Halbzeitpause";
  }
  if (ticker_data.value !== undefined) {
    for (var x = 0; x < ticker_data.value?.length; x++) {
      if (ticker_data.value[x].event == LivetickerEvent.ABORTION) {
        return "Abbruch";
      }
    }
  }

  let pad = function (num: number) {
    var norm = Math.floor(Math.abs(num));
    return (norm < 10 ? "0" : "") + norm;
  };

  return pad(minutes) + ":" + pad(seconds);
});
// Referenz Objekt/Wert
let elapsed_match_seconds: Ref<number | undefined> = ref();

// Ausrechnen der Minute in der sich der Liveticker befindet.
let elapsedMinutes: ComputedRef<number | string> = computed(() => {
  var seconds: number = 0;
  var minutes: number = 0;
  if (
    elapsed_match_seconds.value !== undefined &&
    elapsed_match_seconds.value > 0
  ) {
    seconds = elapsed_match_seconds.value % 60;
    minutes = elapsed_match_seconds.value / 60;
  } else {
    return "Anpfiff";
  }
  if (ticker_info.value?.state == LivetickerState.FIRST_HALF_ENDED) {
    return "Halbzeitpause";
  }
  if (ticker_data.value !== undefined) {
    for (var x = 0; x < ticker_data.value?.length; x++) {
      if (ticker_data.value[x].event == LivetickerEvent.ABORTION) {
        return "Abbruch";
      }
    }
  }

  let pad = function (num: number) {
    var norm = Math.floor(Math.abs(num));
    return (norm < 10 ? "0" : "") + norm;
  };

  return pad(minutes) + ":" + pad(seconds);
});

Sollte sich der LivetickerState innerhalb einer Halbzeit / ähnlichem Zutand befinden wird keine Zeit, sondern ein String ausgespielt.

Halbzeit

In der Halbzeit sind einige Events deaktiviert. Dazu zählen LivetickerEvent.GOAL, LivetickerEvent.YELLOW_CARD, LivetickerEvent.YELLOW_RED_CARD und LivetickerEvent.RED_CARD

Spielende

In diesem Zunstand ist der Liveticker beendet und es können, abgesehen von einem Fazit, nur noch Events editiert werden. In diesem Fall befindet sich der LivetickerState.END.

Events

Beim Anlegen von Events werden unter anderem Modals verwendet. Im TickerView wird hauptsächlich das EventModal genutzt. Weiter gibt es noch ein LineupModal was beim Anlegen von einer Aufstellungen dient. Das TickerStartModal dient zum Erstellen eines Livetickers.

Innerhalb der View wird die Methode createOrUpdateEvent verwendet.

ts
let createOrUpdateEvent = (
  eventId: number | undefined,
  newEventType: number | undefined,
  newEventText: string | undefined
) => {
  is_loading.value = true;
  if (newEventText == undefined) {
    newEventText = "";
  }
  console.log(
    "createOrUpdateEvent: " +
      eventId +
      ", " +
      newEventType +
      ", " +
      newEventText
  );
  var eventType: number | undefined = newEventType;
  if (ticker_info.value !== undefined) {
    /* Vorbericht */
    if (
      eventType == LivetickerEvent.COMMENT &&
      (elapsed_match_seconds.value == undefined || elapsed_match_seconds.value == 0)
    ) {
      eventType = LivetickerEvent.PRE_MATCH_COMMENT;
    } else if (
      eventType == LivetickerEvent.COMMENT &&
      ticker_info.value.state == LivetickerState.END
    ) {
      eventType = LivetickerEvent.POST_MATCH_COMMENT;
    } else if (
      eventType == LivetickerEvent.COMMENT &&
      ticker_info.value.state == LivetickerState.FIRST_HALF_ENDED
    ) {
      eventType = LivetickerEvent.MIDDLE_MATCH_COMMENT;
    }
    /* if (this.ticker_info.id === undefined) { ticker_info.value.id = ticker_info.value.liveticker.id }*/
    // avoid setting fkPlayer = -1
    if (currentEventPlayer1.value == -1) {
      currentEventPlayer1.value = undefined;
    }
    if (currentEventPlayer2.value == -1) {
      currentEventPlayer2.value = undefined;
    }
    // check if fkLiveticker is set or not
    let fkLiveticker_1; 
    if (ticker_info.value.id == undefined) {
      fkLiveticker_1 = ticker_info.value.liveticker?.id;
    } else {
      fkLiveticker_1 = ticker_info.value.id;
    }

    // get elapsed minutes as integer
    let minute: number | undefined;
    if (currentEventMinute.value != undefined && 
        currentEventMinute.value != 0 &&
        eventType != LivetickerEvent.HALF_TIME &&
        eventType != LivetickerEvent.SECOND_HALF &&
        eventType != LivetickerEvent.SECOND_HALF_END &&
        eventType != LivetickerEvent.START_EXTRA_TIME_FIRST_HALF &&
        eventType != LivetickerEvent.END_EXTRA_TIME_FIRST_HALF &&
        eventType != LivetickerEvent.START_EXTRA_TIME_SECOND_HALF &&
        eventType != LivetickerEvent.END_EXTRA_TIME_SECOND_HALF) {
      minute = currentEventMinute.value;
    } else {
      minute =
        elapsed_match_seconds.value != undefined
          ? (elapsed_match_seconds.value / 60) >> 0
          : 0;
    }
    // special case for create event
    if (eventType == LivetickerEvent.KICK_OFF) {
      minute = 1;
    }
    // dispatch
    store
      .createOrUpdateTickerEvent(
        eventId,
        fkLiveticker_1,
        eventType,
        newEventText,
        minute,
        currentEventTeamId.value,
        currentEventPlayer1.value,
        currentEventPlayer2.value,
        currentEventPlayer1Freetext.value,
        currentEventPlayer2Freetext.value,
        currentEventGoalType.value,
        currentEventCardReason.value
      )
      .then((res) => {
        console.log(res);
        if (ticker_info.value !== undefined) {
          ticker_info.value.live_goals = res.liveGoals;
        }
        if (res.error) {
          alert(res.error);
          return;
        }
        if (eventId != undefined) {
          if (ticker_data.value !== undefined) {
            let idx: number = ticker_data.value?.findIndex(
              (el) => el.id == eventId
            );
            if (idx != -1) {
              console.log("replacing old entry...");
              ticker_data.value[idx] = res;
              let x = getCurrentInstance();
              if (x && x.proxy) {
                x.proxy.$forceUpdate();
              }
            }
          }
        } else {
          // init ticker-data
          if (ticker_data.value === undefined) {
            ticker_data.value = [];
          }
          ticker_data.value.push(res);
          if (eventType !== undefined) {
            if (time_events.indexOf(eventType) != -1) {
              startOrAdjustTimer();
            }
          }
        }
        is_loading.value = false;
      });
  }
  show_inputs.value = false;
};
let createOrUpdateEvent = (
  eventId: number | undefined,
  newEventType: number | undefined,
  newEventText: string | undefined
) => {
  is_loading.value = true;
  if (newEventText == undefined) {
    newEventText = "";
  }
  console.log(
    "createOrUpdateEvent: " +
      eventId +
      ", " +
      newEventType +
      ", " +
      newEventText
  );
  var eventType: number | undefined = newEventType;
  if (ticker_info.value !== undefined) {
    /* Vorbericht */
    if (
      eventType == LivetickerEvent.COMMENT &&
      (elapsed_match_seconds.value == undefined || elapsed_match_seconds.value == 0)
    ) {
      eventType = LivetickerEvent.PRE_MATCH_COMMENT;
    } else if (
      eventType == LivetickerEvent.COMMENT &&
      ticker_info.value.state == LivetickerState.END
    ) {
      eventType = LivetickerEvent.POST_MATCH_COMMENT;
    } else if (
      eventType == LivetickerEvent.COMMENT &&
      ticker_info.value.state == LivetickerState.FIRST_HALF_ENDED
    ) {
      eventType = LivetickerEvent.MIDDLE_MATCH_COMMENT;
    }
    /* if (this.ticker_info.id === undefined) { ticker_info.value.id = ticker_info.value.liveticker.id }*/
    // avoid setting fkPlayer = -1
    if (currentEventPlayer1.value == -1) {
      currentEventPlayer1.value = undefined;
    }
    if (currentEventPlayer2.value == -1) {
      currentEventPlayer2.value = undefined;
    }
    // check if fkLiveticker is set or not
    let fkLiveticker_1; 
    if (ticker_info.value.id == undefined) {
      fkLiveticker_1 = ticker_info.value.liveticker?.id;
    } else {
      fkLiveticker_1 = ticker_info.value.id;
    }

    // get elapsed minutes as integer
    let minute: number | undefined;
    if (currentEventMinute.value != undefined && 
        currentEventMinute.value != 0 &&
        eventType != LivetickerEvent.HALF_TIME &&
        eventType != LivetickerEvent.SECOND_HALF &&
        eventType != LivetickerEvent.SECOND_HALF_END &&
        eventType != LivetickerEvent.START_EXTRA_TIME_FIRST_HALF &&
        eventType != LivetickerEvent.END_EXTRA_TIME_FIRST_HALF &&
        eventType != LivetickerEvent.START_EXTRA_TIME_SECOND_HALF &&
        eventType != LivetickerEvent.END_EXTRA_TIME_SECOND_HALF) {
      minute = currentEventMinute.value;
    } else {
      minute =
        elapsed_match_seconds.value != undefined
          ? (elapsed_match_seconds.value / 60) >> 0
          : 0;
    }
    // special case for create event
    if (eventType == LivetickerEvent.KICK_OFF) {
      minute = 1;
    }
    // dispatch
    store
      .createOrUpdateTickerEvent(
        eventId,
        fkLiveticker_1,
        eventType,
        newEventText,
        minute,
        currentEventTeamId.value,
        currentEventPlayer1.value,
        currentEventPlayer2.value,
        currentEventPlayer1Freetext.value,
        currentEventPlayer2Freetext.value,
        currentEventGoalType.value,
        currentEventCardReason.value
      )
      .then((res) => {
        console.log(res);
        if (ticker_info.value !== undefined) {
          ticker_info.value.live_goals = res.liveGoals;
        }
        if (res.error) {
          alert(res.error);
          return;
        }
        if (eventId != undefined) {
          if (ticker_data.value !== undefined) {
            let idx: number = ticker_data.value?.findIndex(
              (el) => el.id == eventId
            );
            if (idx != -1) {
              console.log("replacing old entry...");
              ticker_data.value[idx] = res;
              let x = getCurrentInstance();
              if (x && x.proxy) {
                x.proxy.$forceUpdate();
              }
            }
          }
        } else {
          // init ticker-data
          if (ticker_data.value === undefined) {
            ticker_data.value = [];
          }
          ticker_data.value.push(res);
          if (eventType !== undefined) {
            if (time_events.indexOf(eventType) != -1) {
              startOrAdjustTimer();
            }
          }
        }
        is_loading.value = false;
      });
  }
  show_inputs.value = false;
};