<commit_before>var accessToken = localStorage.getItem("accessToken");

var STATES = {
  INIT: 'init',
  LOADING: 'loading',
  LOADED: 'loaded',
  ERROR: 'error'
};

var dataSource;
var currMediaIndex = -1;
var imgElement;
var lastUpdateAt;
var state = STATES.INIT;
var errorCount = 0;

var imgContainerElement;
var loadingContainerElement;

window.onload = function() {
  imgContainerElement = document.getElementById("imgcontainer");
  imgElement = document.getElementById('mainimg');
  loadingContainerElement = document.getElementById('loadingcontainer');
  loadMedia();
}

function setState(newState) {
  loadingContainerElement.textContent = newState;
  state = newState;
}

function loadMedia() {
  if (state === STATES.LOADING) return;

  var isAlreadyLoaded = (state === STATES.LOADED);
  setState(STATES.LOADING);

  var xhr = new XMLHttpRequest();

  var url = '/photos';
  xhr.open('GET', url);
  xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
  xhr.onload = function(e) {
    if (this.status === 401) {
      // unauthorized
      location = 'https://ran-smart-frame.appspot.com/authorize';
      return;
    } else if (this.status !== 200) {
      setState(STATES.ERROR);
      // Try to reload media in 2 min
      errorCount++;

      // Wait at most 10 minutes for retry
      var retryDelay = Math.min(10, errorCount) * 60 * 1000;
      setTimeout(loadMedia, retryDelay);
      return;
    }

    errorCount = 0;
    lastUpdateAt = new Date();
    dataSource = JSON.parse(this.response);

    setState(STATES.LOADED);

    if (!isAlreadyLoaded) {
      //debug - loadingContainerElement.style.display = 'none';
      imgContainerElement.style.display = 'block';

      showNextPhoto();
    }
  }

  xhr.send();
}

function showNextPhoto() {
  checkMediaFreshness();

  currMediaIndex++;
  if (currMediaIndex > dataSource.Media.length - 1) {
    currMediaIndex = 0;
  }

  imgElement.src = dataSource.Media[currMediaIndex].URL;
  setTimeout(showNextPhoto, 30 * 1000);
}

function checkMediaFreshness() {
  var now = new Date();
  var diffMs = (now - lastUpdateAt);
  var diffMin = diffMs / 1000 / 60;

  if (diffMin > 5) {
    loadMedia();
    return true;
  }

  return false;
}
<commit_msg>Error handling and shuffle media array<commit_after>var accessToken = localStorage.getItem("accessToken");

var STATES = {
  INIT: 'init',
  LOADING: 'loading',
  LOADED: 'loaded',
  ERROR: 'error'
};

var CONSTS = {
  SHOW_PHOTO_DURATION_IN_SECONDS: 20,
  REFRESH_MEDIA_INTERVAL_IN_MINUTES: 5
};

var dataSource;
var mediaToShow;
var currMediaIndex = -1;
var imgElement;
var lastUpdateAt;
var state = STATES.INIT;
var errorCount = 0;

var imgContainerElement;
var loadingContainerElement;

window.onload = function() {
  imgContainerElement = document.getElementById("imgcontainer");
  imgElement = document.getElementById('mainimg');
  loadingContainerElement = document.getElementById('loadingcontainer');
  loadMedia();
}

function setState(newState) {
  loadingContainerElement.textContent = newState;
  state = newState;
}

function setErrorState() {
  setState(STATES.ERROR);
  // Try to reload media in 2 min
  errorCount++;

  // Wait at most 10 minutes for retry
  var retryDelay = Math.min(10, errorCount) * 60 * 1000;
  setTimeout(loadMedia, retryDelay);
}

function loadMedia() {

  if (state === STATES.LOADING) return;

  var isAlreadyLoaded = (state === STATES.LOADED);
  setState(STATES.LOADING);

  var xhr = new XMLHttpRequest();
  xhr.timeout = 8000; //60 * 1000; // timeout of 1 minute

  var url = '/photos';
  xhr.open('GET', url);
  xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);


  xhr.ontimeout = function () {
    setErrorState();
  };

  xhr.onerror = function() {
    setErrorState();
  }

  xhr.onload = function(e) {
    if (this.status === 401) {
      // unauthorized
      location = 'https://ran-smart-frame.appspot.com/authorize';
      return;
    } else if (this.status !== 200) {
      setErrorState();
      return;
    };

    errorCount = 0;
    lastUpdateAt = new Date();
    dataSource = JSON.parse(this.response);
    mediaToShow = dataSource.Media.slice(); // make a copy

    // TODO: we should not suffle if the dataSource is the same as the last one we got to ensure we show all the pictures before suffle again.
    shuffle(mediaToShow);

    setState(STATES.LOADED);

    if (!isAlreadyLoaded) {
      //debug - loadingContainerElement.style.display = 'none';
      imgContainerElement.style.display = 'block';

      showNextPhoto();
    }
  };

  xhr.send();
}

function showNextPhoto() {
  checkMediaFreshness();

  currMediaIndex++;
  if (currMediaIndex > mediaToShow.length - 1) {
    currMediaIndex = 0;
  }

  imgElement.src = mediaToShow[currMediaIndex].URL;
  setTimeout(showNextPhoto, CONSTS.SHOW_PHOTO_DURATION_IN_SECONDS * 1000);
}

function checkMediaFreshness() {
  var now = new Date();
  var diffMs = (now - lastUpdateAt);
  var diffMin = diffMs / 1000 / 60;

  if (diffMin > CONSTS.REFRESH_MEDIA_INTERVAL_IN_MINUTES) {
    loadMedia();
    return true;
  }

  return false;
}

function shuffle(array) {
  var currentIndex = array.length, temporaryValue, randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {

    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    // And swap it with the current element.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
}

{'fraction_non_alphanumeric': 0.12594187298170076, 'fraction_numerical': 0.014890563329745246, 'mean_word_length': 3.54360228198859, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3891689', 'n_tokens_mistral': 1888, 'n_tokens_neox': 1742, 'n_words': 429}