<commit_before>var fs = require('fs');
var path = require('path');
var moment = require('moment');
var execSync = require('child_process').execSync;

// path to the lineup file
var running_dir = process.argv[2];
var lineupFilePath = fs.readFileSync(running_dir + "/lineups/current", 'utf8');
var media_dir = process.argv[3];
var currentClipFilePath = process.argv[4];

var lineup = null;

var findClip = function(programIdx, clipAbsolutePath) {
	var program = lineup.Programs[programIdx];

	if (program.PreShow) {
		for (var i = 0; i < program.PreShow.Clips.length; i++) {
			var cAbsolutePath = path.resolve(media_dir, program.PreShow.Clips[i].Path);
			if (clipAbsolutePath == cAbsolutePath) {
				return program.PreShow.Clips[i];
			}
		}
	}
	for (var i = 0; i < program.Show.Clips.length; i++) {
		var cAbsolutePath = path.resolve(media_dir, program.Show.Clips[i].Path);
		if (clipAbsolutePath == cAbsolutePath) {
			return program.Show.Clips[i];
		}
	}

	return null;
}

if (fs.existsSync(lineupFilePath)) {
	lineup = JSON.parse(fs.readFileSync(lineupFilePath, 'utf8'));
	var currentProgramIdx = parseInt(fs.readFileSync(lineupFilePath + ".program.iter", 'utf8'));

	clip = findClip(currentProgramIdx, currentClipFilePath);

	// might be
	if (!clip) {
		upcomingClipAbsolutePath = path.resolve(media_dir, lineup.Programs[currentProgramIdx + 1].Show.Clips[0].Path)
		if (lineup.Programs[currentProgramIdx + 1] &&
			currentClipFilePath == upcomingClipAbsolutePath) {
			// In case of back-to-back programs, we need to move program iter when the first
			// media of the next program begins to play.
			// Lets shift the current program iterator
			currentProgramIdx++;
			clip = findClip(currentProgramIdx, currentClipFilePath);
			// TODO
			// fs.writeFileSync(lineupFilePath + ".program.iter", currentProgramIdx);
		}
	}

	if (clip) {
		// We have program playing
		status = {};
		status.isCurrentlyPlaying = true;
		status.currentProgram = lineup.Programs[currentProgramIdx].Title;
		status.currentClip = clip.Description ? clip.Description : "";

		fs.writeFileSync(running_dir + "/web/status.json", status);

	} else {
		// No programs right now! Instead publish the countdown
		status = {};
		status.isCurrentlyPlaying = false;
		status.currentProgram = "BLANK";
		status.now = moment().format();

		if (lineup.Programs[currentProgramIdx + 1]) {

			nextProgram = lineup.Programs[currentProgramIdx + 1];
			status.nextBoxId = nextProgram.BoxId;
			status.nextBoxStartTime = nextProgram.PreShow ?
										nextProgram.PreShow.Meta.TentativeStartTime :
										nextProgram.Show.Meta.TentativeStartTime;
		} else {
			// TODO
			// Todays programs is over, we should check the next days lineup
		}

		fs.writeFileSync(running_dir + "/web/status.json", status);
	}
}
<commit_msg>new status system<commit_after>var fs = require('fs');
var path = require('path');
var moment = require('moment');
var execSync = require('child_process').execSync;

// path to the lineup file
var running_dir = process.argv[2];
var lineupFilePath = fs.readFileSync(running_dir + "/lineups/current", 'utf8');
var media_dir = process.argv[3];
var currentClipFilePath = process.argv[4];

var lineup = null;

var findClip = function(programIdx, clipAbsolutePath) {
	var program = lineup.Programs[programIdx];

	if (program.PreShow) {
		for (var i = 0; i < program.PreShow.Clips.length; i++) {
			var cAbsolutePath = path.resolve(media_dir, program.PreShow.Clips[i].Path);
			if (clipAbsolutePath == cAbsolutePath) {
				return program.PreShow.Clips[i];
			}
		}
	}
	for (var i = 0; i < program.Show.Clips.length; i++) {
		var cAbsolutePath = path.resolve(media_dir, program.Show.Clips[i].Path);
		if (clipAbsolutePath == cAbsolutePath) {
			return program.Show.Clips[i];
		}
	}

	return null;
}

if (fs.existsSync(lineupFilePath)) {
	lineup = JSON.parse(fs.readFileSync(lineupFilePath, 'utf8'));
	var currentProgramIdx = parseInt(fs.readFileSync(lineupFilePath + ".program.iter", 'utf8'));

	clip = findClip(currentProgramIdx, currentClipFilePath);

	// might be
	if (!clip) {
		upcomingClipAbsolutePath = path.resolve(media_dir, lineup.Programs[currentProgramIdx + 1].Show.Clips[0].Path)
		if (lineup.Programs[currentProgramIdx + 1] &&
			currentClipFilePath == upcomingClipAbsolutePath) {
			// In case of back-to-back programs, we need to move program iter when the first
			// media of the next program begins to play.
			// Lets shift the current program iterator
			currentProgramIdx++;
			clip = findClip(currentProgramIdx, currentClipFilePath);
			// TODO
			// fs.writeFileSync(lineupFilePath + ".program.iter", currentProgramIdx);
		}
	}

	if (clip) {
		// We have program playing
		status = {};
		status.isCurrentlyPlaying = true;
		status.currentProgram = lineup.Programs[currentProgramIdx].Title;
		status.currentClip = clip.Description ? clip.Description : "";

		fs.writeFileSync(running_dir + "/web/status.json", status);

	} else {
		// No programs right now! Instead publish the countdown
		status = {};
		status.isCurrentlyPlaying = false;
		status.currentProgram = "BLANK";
		status.now = moment().format();

		if (lineup.Programs[currentProgramIdx + 1]) {

			nextProgram = lineup.Programs[currentProgramIdx + 1];
			status.nextBoxId = nextProgram.BoxId;
			status.nextBoxStartTime = nextProgram.PreShow ?
										nextProgram.PreShow.Meta.TentativeStartTime :
										nextProgram.Show.Meta.TentativeStartTime;
		} else {
			// TODO
			// Todays programs is over, we should check the next days lineup
		}

		fs.writeFileSync(running_dir + "/web/status.json", JSON.stringify(status);
	}
}
<|endoftext|>


<commit_before>(function() {
  // The 'Artifact' object abstracts the
  // properties of a release artifact for the CLI.
  this.Artifact = function(path) {
    this.type = "";
    this.name = "";
    this.platform = "";
    this.arch = "";
    this.version = null;
    this.path = path;

    // The 'BinaryVersion' object abstracts the
    // properties of the version for a CLI binary.
    var BinaryVersion = function(major, minor, patch) {
      this.major = major;
      this.minor = major + "." + minor;
      this.patch = major + "." + minor + "." + patch;
    };
    BinaryVersion.prototype.toString = function() {
        return this.patch
    };

    // The 'PluginVersion' object abstracts the
    // properties of the version for a CLI plugin.
    var PluginVersion = function(dcos, patch) {
      this.dcos = dcos;
      this.patch = patch;
    };
    PluginVersion.prototype.toString = function() {
        return this.dcos + "-patch." + this.patch;
    };

    // The 'constructor' function constructs a CLI
    // artifact from a path to a CLI artifact.
    var constructor = function(self, path) {
      parts = path.split('/');

      if (parts[0] !== "releases") {
          throw("Invalid path: Paths to artifacts must follow the scheme" +
                " 'releases/...': " + path);
      }

      switch(parts[1]) {
        case "binaries":
          self.type = "binary";
          break;
        case "plugins":
          self.type = "plugin";
          break;
        default:
          throw("Invalid path: Unrecognized <type> '" + parts[1] + "'" +
                " in scheme 'releases/<type>/... for path '" + path + "'");
      };

      if (self.type === "binary" && parts.length != 7) {
          throw("Invalid path: Paths to 'binaries' must follow the scheme" +
                " 'releases/binaries/<name>/<platform>/<arch>/<version>/<name>{.exe}" +
                " for path '" + path + "'");
      }

      if (self.type === "plugin" && parts.length != 6) {
          throw("Invalid path: Paths to 'plugins' must follow the scheme" +
                " 'releases/plugins/<name>/<platform>/<arch>/<name>-<dcos-version>-patch.<patch-version>.zip'" +
                " for path '" + path + "'");
      }

      self.name = parts[2];

      if (["darwin", "linux", "windows"].indexOf(parts[3]) === -1) {
          throw("Invalid path: Unrecognized <platform> '" + parts[3] + "'" +
                " in scheme 'releases/<type>/<name>/<platform>/...'" +
                " for path '" + path + "'");
      }

      self.platform = parts[3];

      if (["x86-64"].indexOf(parts[4]) === -1) {
          throw("Invalid path: Unrecognized <arch> '" + parts[4] + "'" +
                " in scheme 'releases/<type>/<name>/<platform>/<arch>/...'" +
                " for path '" + path + "'");
      }

      self.arch = parts[4];

      if (self.type === "binary") {
          var regex = /(\d+)\.(\d+).(\d+)/;
          matches = regex.exec(parts[5]);

          if (matches === null) {
              throw("Invalid path: The binary version '" + parts[5] + "'" +
                    " does not match '<major>.<minor>.<patch>' as all" +
                    " numerical digits in scheme " +
                    " 'releases/<type>/<name>/<platform>/<arch>/<version>/...'" +
                    " for path '" + path + "'");
          }

          self.version = new BinaryVersion(matches[1], matches[2], matches[3]);

          if (parts[6] !== self.name && parts[6] !== self.name + ".exe") {
              throw("Invalid path: The binary name '" + parts[6] + "'" +
                    " does not match '<name>{.exe}' in scheme" +
                    " 'releases/<type>/<name>/<platform>/<arch>/<version>/<name>{.exe}'" +
                    " for path '" + path + "'");
          }
      }

      if (self.type == "plugin") {
          var regex = /(.+)-(\d+\.\d+)-patch\.(\d+)\.zip/;
          matches = regex.exec(parts[5]);

          if (matches === null || matches[1] !== self.name) {
              throw("Invalid path: The plugin name '" + parts[5] + "'" +
                    " does not match" +
                    " '<name>-<dcos-version>-patch.<patch-version>.zip' in scheme" +
                    " 'releases/<type>/<name>/<platform>/<arch>/<version>/<name>-<dcos-version>-patch.<patch-version>.zip'" +
                    " for path '" + path + "'");
          }

          self.version = new PluginVersion(matches[2], matches[3]);
      }
    };

    // The 'anchor' function constructs an HTML anchor to
    // an artifact's path, using 'text' as the placeholder
    // text. If 'text' is 'null', the path itself is used as
    // the placeholder text.
    this.anchor = function(text=null) {
      if (text === null) {
        text = this.path
      }
      return '' + text + '';
    }

    constructor(this, path);
  };

  // The 'Artifacts' object defines a collection of
  // functions for working with a set 'Artifact' objects.
  this.Artifacts = function(artifacts) {
    this.artifacts = artifacts;

    // The 'Binaries' object defines a collection of functions
    // for working with a set of binary 'Artifact' objects.
    var Binaries = function(binaries) {
      this.binaries = binaries;

      // List all binary artifacts.
      this.list = function() {
        return this.binaries;
      };

      // List unique major versions across all binaries.
      this.majorVersions = function() {
        var versions = [];
        $.each(this.binaries, function(_, binary) {
          if (versions.indexOf(binary.version.major) === -1) {
            versions.push(binary.version.major);
          }
        });
        return versions;
      };

      // List unique minor versions across all binaries.
      this.minorVersions = function() {
        var versions = [];
        $.each(this.binaries, function(_, binary) {
          version = binary.version.minor;
          if (versions.indexOf(version) === -1) {
            versions.push(version);
          }
        });
        return versions;
      };

      // List unique patch versions across all binaries.
      this.patchVersions = function() {
        var versions = [];
        $.each(this.binaries, function(_, binary) {
          if (versions.indexOf(binary.version.toString()) === -1) {
            versions.push(binary.version.toString());
          }
        });
        return versions;
      };

      // List unique versions across all binaries.
      this.versions = this.patchVersions;

      // List unique platforms across all binaries.
      this.platforms = function() {
        var platforms = [];
        $.each(this.binaries, function(_, binary) {
          if (platforms.indexOf(binary.platform) === -1) {
            platforms.push(binary.platform);
          }
        });
        return platforms;
      };

      // List unique architectures across all binaries.
      this.architectures = function() {
        var architectures = [];
        $.each(this.binaries, function(_, binary) {
          if (architectures.indexOf(binary.arch) === -1) {
            architectures.push(binary.arch);
          }
        });
        return architectures;
      };

      // List unique names across all binaries.
      this.names = function() {
        var names = [];
        $.each(this.binaries, function(_, binary) {
          if (names.indexOf(binary.name) === -1) {
            names.push(binary.name);
          }
        });
        return names;
      };
    };

    // The 'Plugins' object defines a collection of functions
    // for working with a set of plugin 'Artifact' objects.
    var Plugins = function(plugins) {
      this.plugins = plugins;

      // List all plugin artifacts.
      this.list = function() {
        return this.plugins;
      };

      // List unique DC/OS versions across all plugins.
      this.dcosVersions = function() {
        var versions = [];
        $.each(this.plugins, function(_, plugin) {
          if (versions.indexOf(plugin.version.dcos) === -1) {
            versions.push(plugin.version.dcos);
          }
        });
        return versions;
      };

      // List unique patch versions across all plugins.
      this.patchVersions = function() {
        var versions = [];
        $.each(this.plugins, function(_, plugin) {
          if (versions.indexOf(plugin.version.toString()) === -1) {
            versions.push(plugin.version.toString());
          }
        });
        return versions;
      };

      // List unique versions across all plugins.
      this.versions = this.patchVersions;

      // List unique platforms across all plugins.
      this.platforms = function() {
        var platforms = [];
        $.each(this.plugins , function(_, plugin) {
          if (platforms.indexOf(plugin.platform) === -1) {
            platforms.push(plugin.platform);
          }
        });
        return platforms;
      };

      // List unique architectures across all plugins.
      this.architectures = function() {
        var architectures = [];
        $.each(this.plugins , function(_, plugin) {
          if (architectures.indexOf(plugin.arch) === -1) {
            architectures.push(plugin.arch);
          }
        });
        return architectures;
      };

      // List unique names across all plugins.
      this.names = function() {
        var names = [];
        $.each(this.plugins, function(_, plugin) {
          if (names.indexOf(plugin.name) === -1) {
            names.push(plugin.name);
          }
        });
        return names;
      };
    };

    // The 'binaries' function returns a 'Binaries'
    // object representing the set of binary artifacts.
    this.binaries = function() {
      var binaries = this.artifacts.filter(function(artifact) {
        return artifact.type == "binary";
      });
      return new Binaries(binaries);
    };

    // The 'plugins' function returns a 'Plugins'
    // object representing the set of plugin artifacts.
    this.plugins = function() {
      var plugins = this.artifacts.filter(function(artifact) {
        return artifact.type == "plugin";
      });
      return new Plugins(plugins);
    };

    // The 'platforms' function returns a list of
    // platforms across all binaries and plugins.
    this.platforms = function() {
      var platforms = [];
      $.each(this.artifacts, function(_, artifact) {
        if (platforms.indexOf(artifact.platform) === -1) {
          platforms.push(artifact.platform);
        }
      });
      return platforms;
    };

    // The 'architectures' function returns a list of
    // architectures across all binaries and plugins.
    this.architectures = function() {
      var architectures = [];
      $.each(this.artifacts, function(_, artifact) {
        if (architectures.indexOf(artifact.arch) === -1) {
          architectures.push(artifact.arch);
        }
      });
      return architectures;
    };
  };

  // The 'FetchArtifacts' function fetches a list of CLI artifacts from
  // a JSON file and creates an 'Artifacts' object representing them.
  this.FetchArtifacts = function(source, callback) {
    var artifacts = [];

    $.getJSON(source, function(data) {
      $.each(data, function(key, val) {
        if (key != "artifacts") {
          throw("Unknown key in '" + this.source + "': " + key);
        }

        $.each(val, function(i, path) {
          artifacts.push(new Artifact(path));
        });
      });

      callback(new Artifacts(artifacts));
    });
  };
})();
<commit_msg>Updated JSON source for artifacts index to avoid caching.<commit_after>(function() {
  // The 'Artifact' object abstracts the
  // properties of a release artifact for the CLI.
  this.Artifact = function(path) {
    this.type = "";
    this.name = "";
    this.platform = "";
    this.arch = "";
    this.version = null;
    this.path = path;

    // The 'BinaryVersion' object abstracts the
    // properties of the version for a CLI binary.
    var BinaryVersion = function(major, minor, patch) {
      this.major = major;
      this.minor = major + "." + minor;
      this.patch = major + "." + minor + "." + patch;
    };
    BinaryVersion.prototype.toString = function() {
        return this.patch
    };

    // The 'PluginVersion' object abstracts the
    // properties of the version for a CLI plugin.
    var PluginVersion = function(dcos, patch) {
      this.dcos = dcos;
      this.patch = patch;
    };
    PluginVersion.prototype.toString = function() {
        return this.dcos + "-patch." + this.patch;
    };

    // The 'constructor' function constructs a CLI
    // artifact from a path to a CLI artifact.
    var constructor = function(self, path) {
      parts = path.split('/');

      if (parts[0] !== "releases") {
          throw("Invalid path: Paths to artifacts must follow the scheme" +
                " 'releases/...': " + path);
      }

      switch(parts[1]) {
        case "binaries":
          self.type = "binary";
          break;
        case "plugins":
          self.type = "plugin";
          break;
        default:
          throw("Invalid path: Unrecognized <type> '" + parts[1] + "'" +
                " in scheme 'releases/<type>/... for path '" + path + "'");
      };

      if (self.type === "binary" && parts.length != 7) {
          throw("Invalid path: Paths to 'binaries' must follow the scheme" +
                " 'releases/binaries/<name>/<platform>/<arch>/<version>/<name>{.exe}" +
                " for path '" + path + "'");
      }

      if (self.type === "plugin" && parts.length != 6) {
          throw("Invalid path: Paths to 'plugins' must follow the scheme" +
                " 'releases/plugins/<name>/<platform>/<arch>/<name>-<dcos-version>-patch.<patch-version>.zip'" +
                " for path '" + path + "'");
      }

      self.name = parts[2];

      if (["darwin", "linux", "windows"].indexOf(parts[3]) === -1) {
          throw("Invalid path: Unrecognized <platform> '" + parts[3] + "'" +
                " in scheme 'releases/<type>/<name>/<platform>/...'" +
                " for path '" + path + "'");
      }

      self.platform = parts[3];

      if (["x86-64"].indexOf(parts[4]) === -1) {
          throw("Invalid path: Unrecognized <arch> '" + parts[4] + "'" +
                " in scheme 'releases/<type>/<name>/<platform>/<arch>/...'" +
                " for path '" + path + "'");
      }

      self.arch = parts[4];

      if (self.type === "binary") {
          var regex = /(\d+)\.(\d+).(\d+)/;
          matches = regex.exec(parts[5]);

          if (matches === null) {
              throw("Invalid path: The binary version '" + parts[5] + "'" +
                    " does not match '<major>.<minor>.<patch>' as all" +
                    " numerical digits in scheme " +
                    " 'releases/<type>/<name>/<platform>/<arch>/<version>/...'" +
                    " for path '" + path + "'");
          }

          self.version = new BinaryVersion(matches[1], matches[2], matches[3]);

          if (parts[6] !== self.name && parts[6] !== self.name + ".exe") {
              throw("Invalid path: The binary name '" + parts[6] + "'" +
                    " does not match '<name>{.exe}' in scheme" +
                    " 'releases/<type>/<name>/<platform>/<arch>/<version>/<name>{.exe}'" +
                    " for path '" + path + "'");
          }
      }

      if (self.type == "plugin") {
          var regex = /(.+)-(\d+\.\d+)-patch\.(\d+)\.zip/;
          matches = regex.exec(parts[5]);

          if (matches === null || matches[1] !== self.name) {
              throw("Invalid path: The plugin name '" + parts[5] + "'" +
                    " does not match" +
                    " '<name>-<dcos-version>-patch.<patch-version>.zip' in scheme" +
                    " 'releases/<type>/<name>/<platform>/<arch>/<version>/<name>-<dcos-version>-patch.<patch-version>.zip'" +
                    " for path '" + path + "'");
          }

          self.version = new PluginVersion(matches[2], matches[3]);
      }
    };

    // The 'anchor' function constructs an HTML anchor to
    // an artifact's path, using 'text' as the placeholder
    // text. If 'text' is 'null', the path itself is used as
    // the placeholder text.
    this.anchor = function(text=null) {
      if (text === null) {
        text = this.path
      }
      return '' + text + '';
    }

    constructor(this, path);
  };

  // The 'Artifacts' object defines a collection of
  // functions for working with a set 'Artifact' objects.
  this.Artifacts = function(artifacts) {
    this.artifacts = artifacts;

    // The 'Binaries' object defines a collection of functions
    // for working with a set of binary 'Artifact' objects.
    var Binaries = function(binaries) {
      this.binaries = binaries;

      // List all binary artifacts.
      this.list = function() {
        return this.binaries;
      };

      // List unique major versions across all binaries.
      this.majorVersions = function() {
        var versions = [];
        $.each(this.binaries, function(_, binary) {
          if (versions.indexOf(binary.version.major) === -1) {
            versions.push(binary.version.major);
          }
        });
        return versions;
      };

      // List unique minor versions across all binaries.
      this.minorVersions = function() {
        var versions = [];
        $.each(this.binaries, function(_, binary) {
          version = binary.version.minor;
          if (versions.indexOf(version) === -1) {
            versions.push(version);
          }
        });
        return versions;
      };

      // List unique patch versions across all binaries.
      this.patchVersions = function() {
        var versions = [];
        $.each(this.binaries, function(_, binary) {
          if (versions.indexOf(binary.version.toString()) === -1) {
            versions.push(binary.version.toString());
          }
        });
        return versions;
      };

      // List unique versions across all binaries.
      this.versions = this.patchVersions;

      // List unique platforms across all binaries.
      this.platforms = function() {
        var platforms = [];
        $.each(this.binaries, function(_, binary) {
          if (platforms.indexOf(binary.platform) === -1) {
            platforms.push(binary.platform);
          }
        });
        return platforms;
      };

      // List unique architectures across all binaries.
      this.architectures = function() {
        var architectures = [];
        $.each(this.binaries, function(_, binary) {
          if (architectures.indexOf(binary.arch) === -1) {
            architectures.push(binary.arch);
          }
        });
        return architectures;
      };

      // List unique names across all binaries.
      this.names = function() {
        var names = [];
        $.each(this.binaries, function(_, binary) {
          if (names.indexOf(binary.name) === -1) {
            names.push(binary.name);
          }
        });
        return names;
      };
    };

    // The 'Plugins' object defines a collection of functions
    // for working with a set of plugin 'Artifact' objects.
    var Plugins = function(plugins) {
      this.plugins = plugins;

      // List all plugin artifacts.
      this.list = function() {
        return this.plugins;
      };

      // List unique DC/OS versions across all plugins.
      this.dcosVersions = function() {
        var versions = [];
        $.each(this.plugins, function(_, plugin) {
          if (versions.indexOf(plugin.version.dcos) === -1) {
            versions.push(plugin.version.dcos);
          }
        });
        return versions;
      };

      // List unique patch versions across all plugins.
      this.patchVersions = function() {
        var versions = [];
        $.each(this.plugins, function(_, plugin) {
          if (versions.indexOf(plugin.version.toString()) === -1) {
            versions.push(plugin.version.toString());
          }
        });
        return versions;
      };

      // List unique versions across all plugins.
      this.versions = this.patchVersions;

      // List unique platforms across all plugins.
      this.platforms = function() {
        var platforms = [];
        $.each(this.plugins , function(_, plugin) {
          if (platforms.indexOf(plugin.platform) === -1) {
            platforms.push(plugin.platform);
          }
        });
        return platforms;
      };

      // List unique architectures across all plugins.
      this.architectures = function() {
        var architectures = [];
        $.each(this.plugins , function(_, plugin) {
          if (architectures.indexOf(plugin.arch) === -1) {
            architectures.push(plugin.arch);
          }
        });
        return architectures;
      };

      // List unique names across all plugins.
      this.names = function() {
        var names = [];
        $.each(this.plugins, function(_, plugin) {
          if (names.indexOf(plugin.name) === -1) {
            names.push(plugin.name);
          }
        });
        return names;
      };
    };

    // The 'binaries' function returns a 'Binaries'
    // object representing the set of binary artifacts.
    this.binaries = function() {
      var binaries = this.artifacts.filter(function(artifact) {
        return artifact.type == "binary";
      });
      return new Binaries(binaries);
    };

    // The 'plugins' function returns a 'Plugins'
    // object representing the set of plugin artifacts.
    this.plugins = function() {
      var plugins = this.artifacts.filter(function(artifact) {
        return artifact.type == "plugin";
      });
      return new Plugins(plugins);
    };

    // The 'platforms' function returns a list of
    // platforms across all binaries and plugins.
    this.platforms = function() {
      var platforms = [];
      $.each(this.artifacts, function(_, artifact) {
        if (platforms.indexOf(artifact.platform) === -1) {
          platforms.push(artifact.platform);
        }
      });
      return platforms;
    };

    // The 'architectures' function returns a list of
    // architectures across all binaries and plugins.
    this.architectures = function() {
      var architectures = [];
      $.each(this.artifacts, function(_, artifact) {
        if (architectures.indexOf(artifact.arch) === -1) {
          architectures.push(artifact.arch);
        }
      });
      return architectures;
    };
  };

  // The 'FetchArtifacts' function fetches a list of CLI artifacts from
  // a JSON file and creates an 'Artifacts' object representing them.
  this.FetchArtifacts = function(source, callback) {
    var artifacts = [];

    // Append a random string to the end of the JSON
    // file source URL to force it to never be cached.
    source = source + '?nocache=' + (new Date()).getTime();

    $.getJSON(source, function(data) {
      $.each(data, function(key, val) {
        if (key != "artifacts") {
          throw("Unknown key in '" + this.source + "': " + key);
        }

        $.each(val, function(i, path) {
          artifacts.push(new Artifact(path));
        });
      });

      callback(new Artifacts(artifacts));
    });
  };
})();
<|endoftext|>


<commit_before>// @flow
import uuid from 'uuid'
import { satisfies } from 'semver'
import { ContentPlugin, LayoutPlugin, Plugin } from './classes'
import MissingPlugin from 'src/editor/plugins/content/missing'
import slatePluginCreator from 'src/editor/plugins/content/slate'
import ImagePlugin from 'src/editor/plugins/content/image'
import VideoPlugin from 'src/editor/plugins/content/video'
import SpacerPlugin from 'src/editor/plugins/content/spacer'
import DividerPlugin from 'src/editor/plugins/content/divider'
import SpoilerPlugin from 'src/editor/plugins/layout/spoiler'

/**
 * A list of content plugins that are being loaded by default.
 */
export const defaultContentPlugins: [] = [
  MissingPlugin,
  ImagePlugin,
  SpacerPlugin,
  slatePluginCreator(),
  VideoPlugin,
  DividerPlugin
]

/**
 * A list of layout plugins that are being loaded by default.
 */
export const defaultLayoutPlugins: [] = [
  SpoilerPlugin
]

const find = (name: string, version: string = '*') => (plugin: Plugin): boolean => plugin.name === name && satisfies(plugin.version, version)

/**
 * Iterate through an editable content tree and generate ids where missing.
 */
export const generateMissingIds = (props: Object): Object => {
  const { rows, cells, id } = props

  if ((rows || []).length > 0) {
    props.rows = rows.map(generateMissingIds)
  } else if ((cells || []).length > 0) {
    props.cells = cells.map(generateMissingIds)
  }

  return { ...props, id: id || uuid.v4() }
}

/**
 * PluginService is a registry of all content and layout plugins known to the editor.
 */
export default class PluginService {
  plugins: {
    content: Array<ContentPlugin>,
    layout: Array<LayoutPlugin>,
  }

  /**
   * Instantiate a new PluginService instance. You can provide your own set of content and layout plugins here.
   */
  constructor(contentPlugins: [] = defaultContentPlugins, layoutPlugins: [] = defaultLayoutPlugins) {
    this.plugins = {
      content: contentPlugins.map((config: any) => new ContentPlugin(config)),
      layout: layoutPlugins.map((config: any) => new LayoutPlugin(config)),
    }
  }

  /**
   * Finds a layout plugin based on its name and version.
   */
  findLayoutPlugin(name: string, version: string): LayoutPlugin {
    const plugin = this.plugins.layout.find(find(name, version))

    // TODO return a default layout plugin here instead
    if (!plugin) {
      throw new Error(`Plugin ${name} with version ${version} not found`)
    }

    return plugin
  }

  /**
   * Finds a content plugin based on its name and version.
   */
  findContentPlugin(name: string, version: string): ContentPlugin {
    const plugin = this.plugins.content.find(find(name, version))
    return plugin || new ContentPlugin(MissingPlugin)
  }

  /**
   * Returns a list of all known plugin names.
   */
  getRegisteredNames(): Array<string> {
    return [
      ...this.plugins.content.map(({ name }: Plugin) => name),
      ...this.plugins.layout.map(({ name }: Plugin) => name)
    ]
  }

  unserialize = (state: any): Object => {
    const {
      rows = [],
      cells = [],
      content = {},
      layout = {},
      id
    } = state
    const newState: Object = { id }

    const { plugin: { name: contentName = null, version: contentVersion = '*' } = {}, state: contentState } = content || {}
    const { plugin: { name: layoutName = null, version: layoutVersion = '*' } = {}, state: layoutState } = layout || {}

    if (contentName) {
      const plugin = this.findContentPlugin(contentName, contentVersion)
      newState.content = {
        plugin,
        state: plugin.unserialize(contentState)
      }
    }

    if (layoutName) {
      const plugin = this.findLayoutPlugin(layoutName, layoutVersion)
      newState.layout = {
        plugin,
        state: plugin.unserialize(layoutState)
      }
    }

    if ((rows || []).length) {
      newState.rows = rows.map(this.unserialize)
    }

    if ((cells || []).length) {
      newState.cells = cells.map(this.unserialize)
    }

    return generateMissingIds(newState)
  }

  serialize = (state: {
    id: string,
    rows: Object[],
    cells: Object[],
    content: {
      plugin: ContentPlugin,
      state: Object
    },
    layout: {
      plugin: LayoutPlugin,
      state: Object
    },
    props: any
  }): Object => {
    const {
      rows,
      cells,
      content,
      layout,
      id
    } = state

    const newState: Object = { id }
    if (content) {
      newState.content = {
        plugin: { name: content.plugin.name, version: content.plugin.version },
        state: content.plugin.serialize(content.state)
      }
    }

    if (layout) {
      newState.layout = {
        plugin: { name: layout.plugin.name, version: layout.plugin.version },
        state: layout.plugin.serialize(layout.state)
      }
    }

    if ((rows || []).length) {
      newState.rows = rows.map(this.serialize)
    }

    if ((cells || []).length) {
      newState.cells = cells.map(this.serialize)
    }

    return newState
  }
}
<commit_msg>core: serialize should not remove size and inline keys<commit_after>// @flow
import uuid from 'uuid'
import { satisfies } from 'semver'
import { ContentPlugin, LayoutPlugin, Plugin } from './classes'
import MissingPlugin from 'src/editor/plugins/content/missing'
import slatePluginCreator from 'src/editor/plugins/content/slate'
import ImagePlugin from 'src/editor/plugins/content/image'
import VideoPlugin from 'src/editor/plugins/content/video'
import SpacerPlugin from 'src/editor/plugins/content/spacer'
import DividerPlugin from 'src/editor/plugins/content/divider'
import SpoilerPlugin from 'src/editor/plugins/layout/spoiler'

/**
 * A list of content plugins that are being loaded by default.
 */
export const defaultContentPlugins: [] = [
  MissingPlugin,
  ImagePlugin,
  SpacerPlugin,
  slatePluginCreator(),
  VideoPlugin,
  DividerPlugin
]

/**
 * A list of layout plugins that are being loaded by default.
 */
export const defaultLayoutPlugins: [] = [
  SpoilerPlugin
]

const find = (name: string, version: string = '*') => (plugin: Plugin): boolean => plugin.name === name && satisfies(plugin.version, version)

/**
 * Iterate through an editable content tree and generate ids where missing.
 */
export const generateMissingIds = (props: Object): Object => {
  const { rows, cells, id } = props

  if ((rows || []).length > 0) {
    props.rows = rows.map(generateMissingIds)
  } else if ((cells || []).length > 0) {
    props.cells = cells.map(generateMissingIds)
  }

  return { ...props, id: id || uuid.v4() }
}

/**
 * PluginService is a registry of all content and layout plugins known to the editor.
 */
export default class PluginService {
  plugins: {
    content: Array<ContentPlugin>,
    layout: Array<LayoutPlugin>,
  }

  /**
   * Instantiate a new PluginService instance. You can provide your own set of content and layout plugins here.
   */
  constructor(contentPlugins: [] = defaultContentPlugins, layoutPlugins: [] = defaultLayoutPlugins) {
    this.plugins = {
      content: contentPlugins.map((config: any) => new ContentPlugin(config)),
      layout: layoutPlugins.map((config: any) => new LayoutPlugin(config)),
    }
  }

  /**
   * Finds a layout plugin based on its name and version.
   */
  findLayoutPlugin(name: string, version: string): LayoutPlugin {
    const plugin = this.plugins.layout.find(find(name, version))

    // TODO return a default layout plugin here instead
    if (!plugin) {
      throw new Error(`Plugin ${name} with version ${version} not found`)
    }

    return plugin
  }

  /**
   * Finds a content plugin based on its name and version.
   */
  findContentPlugin(name: string, version: string): ContentPlugin {
    const plugin = this.plugins.content.find(find(name, version))
    return plugin || new ContentPlugin(MissingPlugin)
  }

  /**
   * Returns a list of all known plugin names.
   */
  getRegisteredNames(): Array<string> {
    return [
      ...this.plugins.content.map(({ name }: Plugin) => name),
      ...this.plugins.layout.map(({ name }: Plugin) => name)
    ]
  }

  unserialize = (state: any): Object => {
    const {
      rows = [],
      cells = [],
      content = {},
      layout = {},
      inline,
      size,
      id
    } = state
    const newState: Object = { id, inline, size }

    const { plugin: { name: contentName = null, version: contentVersion = '*' } = {}, state: contentState } = content || {}
    const { plugin: { name: layoutName = null, version: layoutVersion = '*' } = {}, state: layoutState } = layout || {}

    if (contentName) {
      const plugin = this.findContentPlugin(contentName, contentVersion)
      newState.content = {
        plugin,
        state: plugin.unserialize(contentState)
      }
    }

    if (layoutName) {
      const plugin = this.findLayoutPlugin(layoutName, layoutVersion)
      newState.layout = {
        plugin,
        state: plugin.unserialize(layoutState)
      }
    }

    if ((rows || []).length) {
      newState.rows = rows.map(this.unserialize)
    }

    if ((cells || []).length) {
      newState.cells = cells.map(this.unserialize)
    }

    return generateMissingIds(newState)
  }

  serialize = (state: Object): Object => {
    const {
      rows,
      cells,
      content,
      layout,
      inline,
      size,
      id
    } = state

    const newState: Object = { id, inline, size }
    if (content) {
      newState.content = {
        plugin: { name: content.plugin.name, version: content.plugin.version },
        state: content.plugin.serialize(content.state)
      }
    }

    if (layout) {
      newState.layout = {
        plugin: { name: layout.plugin.name, version: layout.plugin.version },
        state: layout.plugin.serialize(layout.state)
      }
    }

    if ((rows || []).length) {
      newState.rows = rows.map(this.serialize)
    }

    if ((cells || []).length) {
      newState.cells = cells.map(this.serialize)
    }

    return newState
  }
}
<|endoftext|>


<commit_before>define(['jquery','app/API','underscore','./computeD','./msgCat','./parcelMng'],function($,API,_,computeData,msgMan,parcelMng){

	var Scorer = {};

	$.extend(Scorer, {

		addSettings: function(type,Obj){

			if (type =="compute"){
				computeData.setComputeObject(Obj);

			}else{
				if (type =="message") msgMan.setMsgObject(Obj);

			}

		},

		computeD: function(Obj){

			computeData.setDataArray();
			var score = 0;
			console.log('started computeD');
			console.log(computeData);
			console.log(msgMan);
			var error = parcelMng.Init();
			parcelMng.avgAll();
			parcelMng.diffAll();
			parcelMng.varianceAll();
			score = parcelMng.scoreAll();
			console.log('the score is: '+ score);
	//		var oldScore = parcelMng.simulateOldCode();//for testing only
	//		console.log('the score from old scoree is: '+oldScore );

			return score;

		},

		getInfo: function(){

			//return computeData;

		},

    	postToServer: function(url,score,msg){
    		var data = {};
    		data.score =score;
    		data.msg = msg;

    		$.post(url,data).done( function(retdata){
    			console.log(retdata);

    		});

    	},

      	// get message according to user input
    	getFBMsg: function(DScore, Obj){

    		var msg = msgMan.getMsg(DScore);
    		return msg;

    	}

	});
	return Scorer;
});
<commit_msg>scorer with post to server method<commit_after>define(['jquery','app/API','underscore','./computeD','./msgCat','./parcelMng'],function($,API,_,computeData,msgMan,parcelMng){

	var Scorer = {};

//comment

	$.extend(Scorer, {

		addSettings: function(type,Obj){

			if (type =="compute"){
				computeData.setComputeObject(Obj);

			}else{
				if (type =="message") msgMan.setMsgObject(Obj);

			}

		},

		computeD: function(Obj){

			computeData.setDataArray();
			var score = 0;
			console.log('started computeD');
			console.log(computeData);
			console.log(msgMan);
			var error = parcelMng.Init();
			parcelMng.avgAll();
			parcelMng.diffAll();
			parcelMng.varianceAll();
			score = parcelMng.scoreAll();
			console.log('the score is: '+ score);
	//		var oldScore = parcelMng.simulateOldCode();//for testing only
	//		console.log('the score from old scoree is: '+oldScore );

			return score;

		},

		getInfo: function(){

			//return computeData;

		},

    	postToServer: function(score,msg){

    		var postSettings = computeData.postSettings;
    		var url = postSettings.url;
    		var scoreKey = postSettings.score;
    		var msgKey = postSettings.msg;
    		var data = {};
    		data[scoreKey] =score;
    		data[msgKey] = msg;

    		$.post(url,JSON.stringify(data));

    	},

      	// get message according to user input
    	getFBMsg: function(DScore, Obj){

    		var msg = msgMan.getMsg(DScore);
    		return msg;

    	}

	});
	return Scorer;
});
<|endoftext|>


<commit_before>/**
 * Created by tom on 7/21/14.
 */
/**
 * @classDestription - City of Chicago Warming Centers variables and functions.
 * @class - WarmingCenters
 */
var WarmingCenters;
WarmingCenters = (function ($) {
	var constructor = function () {

		this.Markers = [];
		this.Info = [];

		this.getCenters = function (WC, Map) {
			$.support.cors = true; //enables cross domain support
			$.ajax({
				type: "GET",
				url: 'http://data.cityofchicago.org/resource/h243-v2q5.json',
				dataType: "json",
				success: function (data) {
					var x = 0;
					for (var i in data) {
						console.log(data[i].location.latitude);
						WC.Markers[x] = new google.maps.Marker({
							position: new google.maps.LatLng(data[i].location.latitude, data[i].location.longitude),
							map: Map,
							clickable: true
						});
						WC.Info[x] = new google.maps.InfoWindow({
							content: 'Monday: ' + data[i].monday_open + ' to ' + data[i].monday_close
						});

						google.maps.event.addListener(WC.Markers[x], 'click', function(innerKey) {
							return function() {
								WC.Info[innerKey].open(Map, WC.Markers[innerKey]);
							}
						}(x));
						x++;
					}
				}
			});
		}
	};
	return constructor;

})(jQuery);<commit_msg>a bunch of work<commit_after>/**
 * Created by tom on 7/21/14.
 */
/**
 * @classDestription - City of Chicago Warming Centers variables and functions.
 * @class - WarmingCenters
 */
var WarmingCenters;
WarmingCenters = (function ($) {
	var constructor = function () {

		this.Markers = [];
		this.Info = [];

		this.getCenters = function (WC, Map) {
			console.log('here');
			$.support.cors = true; //enables cross domain support
			$.ajax({
				type: "GET",
				url: 'http://data.cityofchicago.org/resource/h243-v2q5.json',
				dataType: "json",
				success: function (data) {
					console.log(data);
					var x = 0;
					for (var i in data) {
						console.log(data[i].location.latitude);
						WC.Markers[x] = new google.maps.Marker({
							position: new google.maps.LatLng(data[i].location.latitude, data[i].location.longitude),
							map: Map,
							clickable: true
						});
						WC.Info[x] = new google.maps.InfoWindow({
							content: 'Monday: ' + data[i].monday_open + ' to ' + data[i].monday_close
						});

						google.maps.event.addListener(WC.Markers[x], 'click', function(innerKey) {
							return function() {
								WC.Info[innerKey].open(Map, WC.Markers[innerKey]);
							}
						}(x));
						x++;
					}
				}
			});
		}
	};
	return constructor;

})(jQuery);<|endoftext|>


<commit_before>if (typeof (require) != 'undefined') {
	var loader = require('../../node_modules/Butterfly-js/dist/butterfly.min.js').loader;
}

/**
 * Entry point of the game, contains some part of the game engine and deals with
 * the different entities
 */
loader.executeModule('main',
'B', 'Canvas', 'Entities', 'Physics', 'Utils', 'data', 'Controls', 'Level', 'GUI',
function (B, canvas, Entities, Physics, Utils, data, Controls, Level, GUI) {
	var level,
		walls = [],
		// position of the mouse in the canvas, taking in account the scroll
		// and position of the canvas in the page
		mouseX,
		mouseY,
		nbPlayers = 2,
		players = [],
		fps = 30,
		urlParams = Utils.getUrlParams(window.location.search);

	const DEBUG = urlParams.debug || NO_DEBUG;

	B.on(window, 'load', function () {
		// Init the view
		canvas.init(document.getElementById('game-canvas'));
		Controls.init(true);

		loadResources(function () {
			setInterval(updateAll, 1000 / fps);

			level = Level.createLevel(data, 0);

			// Init the car

			for (var p = 0; p < data.maps[0].start.length && p < nbPlayers; p++) {
				var startCell = level.getCoordinatesCenterCell(data.maps[0].start[p][0], data.maps[0].start[p][1]),
					car = new Entities.Car(startCell[0], startCell[1], Math.PI / 2, CAR_SPEED);
				car.setGraphic(data.resources[data.resourcesMap.CAR].resource);
				players.push(car);
			}
		});

		function key (code, pressed, car, gasKey, reverseKey, leftKey, rightKey) {
			if (code == leftKey) {
				car.steerLeft(pressed);
			}
			else if (code == gasKey) {
				car.accelerate(pressed);
			}
			else if (code == rightKey) {
				car.steerRight(pressed);
			}
			else if (code == reverseKey) {
				car.reverse(pressed);
			}
		}

		var controlsPlayers = [
			[KEY_UP_ARROW, KEY_DOWN_ARROW, KEY_LEFT_ARROW, KEY_RIGHT_ARROW],
			[KEY_W, KEY_S, KEY_A, KEY_D]
		];

		B.Events.on('keydown', null, function (code) {
			for (var p = 0; p < nbPlayers; p++) {
				key(code, true, players[p],
					controlsPlayers[p][0], controlsPlayers[p][1], controlsPlayers[p][2], controlsPlayers[p][3]
				);
			}
		});

		B.Events.on('keyup', null, function (code) {
			for (var p = 0; p < nbPlayers; p++) {
				key(code, false,
					players[p], controlsPlayers[p][0], controlsPlayers[p][1], controlsPlayers[p][2], controlsPlayers[p][3]
				);
			}
		});
	});

	/* Events */
	// Event to execute when the player wins
	B.Events.on('win', null, function () {
		for (var p = 0; p < nbPlayers; p++) {
			players[p].reset();
		}
	});

	// Event to execute when the player loses
	B.Events.on('lost', null, function () {
	});

	// Event to execute when the mouse move
	B.Events.on('mouse-moved', null, function (mX, mY) {
		mouseX = mX;
		mouseY = mY;
	});
	/* End of Events */

	function loadResources (loadedCallback) {
		var r, loaded = 0,
			loadingPadding = canvas.width() / 5,
			loadingWidth = 3 * loadingPadding;

		if (!data.resources) {
			loadedCallback();
			return;
		}

		canvas.clearScreen();
		GUI.progressBar(
			loadingPadding, canvas.height() / 2,
			loadingWidth, 30,
			0,
			'black', 'white', 'black'
		);
		for (r = 0; r < data.resources.length; r++) {
			data.resources[r].resource = new Image();
			data.resources[r].resource.onload = function () {
				if (++loaded == data.resources.length) {
					loadedCallback();
				}
				else {
					GUI.progressBar(
						loadingPadding, canvas.height() / 2,
						loadingWidth, 30,
						loaded / data.resources.length,
						'black', 'white', 'black'
					);
				}
			};
			data.resources[r].resource.src = data.resources[r].url;
		}
	}

	/**
	 * Method to update the game state and the objects's position
	 */
	function moveAll () {
		for (var p = 0; p < nbPlayers; p++) {
			// Update the cars position
			players[p].updatePosition();

			var carGridCellCol = Math.floor(players[p].x / level.gridCellWidth),
				carGridCellRow = Math.floor(players[p].y / level.gridCellHeight);

			/* Car and edges collision*/
			Physics.sphereBounceAgainstInnerRectangle(players[p], {x: 0, y: 0, w: canvas.width(), h: canvas.height()});
			/* End of Car and edges collision*/

			/* Car and wall collision */
			var wall = level.getCell(
				carGridCellCol,
				carGridCellRow
			);

			// if the car is on a wall
			if (0 <= carGridCellCol && carGridCellCol < level.width
				&& 0 <= carGridCellRow && carGridCellRow < level.height
				&& data.resources[wall.state].obstacle
			) {
				players[p].bumpBack();
			}
			/* End of Car and wall collision */
		}
	}

	/**
	 * Method to execute on each frame to update the game state and the
	 * objects's position and then redraw the canvas
	 */
	function updateAll () {
		moveAll();
		canvas.drawAll([level.cells, players]);
	}
});
<commit_msg>controls given as an object<commit_after>if (typeof (require) != 'undefined') {
	var loader = require('../../node_modules/Butterfly-js/dist/butterfly.min.js').loader;
}

/**
 * Entry point of the game, contains some part of the game engine and deals with
 * the different entities
 */
loader.executeModule('main',
'B', 'Canvas', 'Entities', 'Physics', 'Utils', 'data', 'Controls', 'Level', 'GUI',
function (B, canvas, Entities, Physics, Utils, data, Controls, Level, GUI) {
	var level,
		walls = [],
		// position of the mouse in the canvas, taking in account the scroll
		// and position of the canvas in the page
		mouseX,
		mouseY,
		nbPlayers = 2,
		players = [],
		playerControls = [
			{gasKey: KEY_UP_ARROW, reverseKey: KEY_DOWN_ARROW, leftKey: KEY_LEFT_ARROW, rightKey: KEY_RIGHT_ARROW},
			{gasKey: KEY_W, reverseKey: KEY_S, leftKey: KEY_A, rightKey: KEY_D}
		];
		fps = 30,
		urlParams = Utils.getUrlParams(window.location.search);

	const DEBUG = urlParams.debug || NO_DEBUG;

	B.on(window, 'load', function () {
		// Init the view
		canvas.init(document.getElementById('game-canvas'));
		Controls.init(true);

		loadResources(function () {
			setInterval(updateAll, 1000 / fps);

			level = Level.createLevel(data, 0);

			// Init the car

			for (var p = 0; p < data.maps[0].start.length && p < nbPlayers; p++) {
				var startCell = level.getCoordinatesCenterCell(data.maps[0].start[p][0], data.maps[0].start[p][1]),
					car = new Entities.Car(startCell[0], startCell[1], Math.PI / 2, CAR_SPEED);
				car.setGraphic(data.resources[data.resourcesMap.CAR].resource);
				players.push(car);
			}
		});

		function key (code, pressed, car, controls) {
			if (code == controls.leftKey) {
				car.steerLeft(pressed);
			}
			else if (code == controls.gasKey) {
				car.accelerate(pressed);
			}
			else if (code == controls.rightKey) {
				car.steerRight(pressed);
			}
			else if (code == controls.reverseKey) {
				car.reverse(pressed);
			}
		}

		B.Events.on('keydown', null, function (code) {
			for (var p = 0; p < nbPlayers; p++) {
				key(code, true, players[p], playerControls[p]);
			}
		});

		B.Events.on('keyup', null, function (code) {
			for (var p = 0; p < nbPlayers; p++) {
				key(code, false, players[p], playerControls[p]);
			}
		});
	});

	/* Events */
	// Event to execute when the player wins
	B.Events.on('win', null, function () {
		for (var p = 0; p < nbPlayers; p++) {
			players[p].reset();
		}
	});

	// Event to execute when the player loses
	B.Events.on('lost', null, function () {
	});

	// Event to execute when the mouse move
	B.Events.on('mouse-moved', null, function (mX, mY) {
		mouseX = mX;
		mouseY = mY;
	});
	/* End of Events */

	function loadResources (loadedCallback) {
		var r, loaded = 0,
			loadingPadding = canvas.width() / 5,
			loadingWidth = 3 * loadingPadding;

		if (!data.resources) {
			loadedCallback();
			return;
		}

		canvas.clearScreen();
		GUI.progressBar(
			loadingPadding, canvas.height() / 2,
			loadingWidth, 30,
			0,
			'black', 'white', 'black'
		);
		for (r = 0; r < data.resources.length; r++) {
			data.resources[r].resource = new Image();
			data.resources[r].resource.onload = function () {
				if (++loaded == data.resources.length) {
					loadedCallback();
				}
				else {
					GUI.progressBar(
						loadingPadding, canvas.height() / 2,
						loadingWidth, 30,
						loaded / data.resources.length,
						'black', 'white', 'black'
					);
				}
			};
			data.resources[r].resource.src = data.resources[r].url;
		}
	}

	/**
	 * Method to update the game state and the objects's position
	 */
	function moveAll () {
		for (var p = 0; p < nbPlayers; p++) {
			// Update the cars position
			players[p].updatePosition();

			var carGridCellCol = Math.floor(players[p].x / level.gridCellWidth),
				carGridCellRow = Math.floor(players[p].y / level.gridCellHeight);

			/* Car and edges collision*/
			Physics.sphereBounceAgainstInnerRectangle(players[p], {x: 0, y: 0, w: canvas.width(), h: canvas.height()});
			/* End of Car and edges collision*/

			/* Car and wall collision */
			var wall = level.getCell(
				carGridCellCol,
				carGridCellRow
			);

			// if the car is on a wall
			if (0 <= carGridCellCol && carGridCellCol < level.width
				&& 0 <= carGridCellRow && carGridCellRow < level.height
				&& data.resources[wall.state].obstacle
			) {
				players[p].bumpBack();
			}
			/* End of Car and wall collision */
		}
	}

	/**
	 * Method to execute on each frame to update the game state and the
	 * objects's position and then redraw the canvas
	 */
	function updateAll () {
		moveAll();
		canvas.drawAll([level.cells, players]);
	}
});
<|endoftext|>


<commit_before>/******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId]) {
/******/ 			return installedModules[moduleId].exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			i: moduleId,
/******/ 			l: false,
/******/ 			exports: {}
/******/ 		};
/******/
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ 		// Flag the module as loaded
/******/ 		module.l = true;
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/
/******/
/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;
/******/
/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;
/******/
/******/ 	// define getter function for harmony exports
/******/ 	__webpack_require__.d = function(exports, name, getter) {
/******/ 		if(!__webpack_require__.o(exports, name)) {
/******/ 			Object.defineProperty(exports, name, {
/******/ 				configurable: false,
/******/ 				enumerable: true,
/******/ 				get: getter
/******/ 			});
/******/ 		}
/******/ 	};
/******/
/******/ 	// getDefaultExport function for compatibility with non-harmony modules
/******/ 	__webpack_require__.n = function(module) {
/******/ 		var getter = module && module.__esModule ?
/******/ 			function getDefault() { return module['default']; } :
/******/ 			function getModuleExports() { return module; };
/******/ 		__webpack_require__.d(getter, 'a', getter);
/******/ 		return getter;
/******/ 	};
/******/
/******/ 	// Object.prototype.hasOwnProperty.call
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";
/******/
/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(__webpack_require__.s = 2);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";

/* harmony default export */ __webpack_exports__["a"] = (({ feedUrl, image, artist, title }) => {
    const data = { feedUrl, image, artist, title };
    return `

${title}

`;
});

/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";

// read config from localStorage and assign with data from network
const KEY = 'podspace_config';
const config = JSON.parse(localStorage.getItem(KEY) || 'null') || {};
const promise = fetch(`${location.href}config/config.json`)
    .then(res => res.json())
    .then(configData => {
    const env = /localhost/i.test(location.hostname) ? 'dev' : 'prod';
    Object.assign(config, configData[env]);
    return config;
});
const get = (key) => {
    return config[key];
};
/* unused harmony export get */

const set = (key, value) => {
    config[key] = value;
    localStorage.setItem(KEY, JSON.stringify(config));
};
/* unused harmony export set */

const ready = () => {
    return promise;
};
/* harmony export (immutable) */ __webpack_exports__["b"] = ready;

/* harmony default export */ __webpack_exports__["a"] = ({ get, set, ready });

/***/ }),
/* 2 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__audioPlayer_js__ = __webpack_require__(3);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__components_searchResultList_js__ = __webpack_require__(4);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__components_userShowList_js__ = __webpack_require__(5);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__components_show_js__ = __webpack_require__(6);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__userData_js__ = __webpack_require__(8);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__components_modal_js__ = __webpack_require__(9);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__audioSearchClient_js__ = __webpack_require__(10);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__config_js__ = __webpack_require__(1);

// https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/
// const SEARCH_BASE = '//itunes.apple.com/search?media=podcast&entity=podcast&limit=25&term=';
Object(__WEBPACK_IMPORTED_MODULE_7__config_js__["b" /* ready */])().then(_ => console.info('CONFIG LOADED!'));
window.addEventListener('load', function () {
    let timeout;
    document.querySelector('input').addEventListener('keyup', event => {
        if (event.target instanceof HTMLInputElement) {
            const query = event.target.value;
            clearTimeout(timeout);
            timeout = setTimeout(() => {
                doSearch(query);
            }, 250);
        }
    });
    renderUserShows();
    window.addEventListener('online', notifyConnection);
    window.addEventListener('offline', notifyConnection);
    function notifyConnection(event) {
        const addRemove = navigator.onLine ? 'remove' : 'add';
        document.body.classList[addRemove]('offline');
        document.querySelector('input').disabled = !navigator.onLine;
        document.querySelector('input').placeholder = navigator.onLine ? 'Search...' : 'Offline...';
        console.warn(navigator.onLine ? 'online :)' : 'offline :(');
    }
});
function doSearch(query) {
    if (!query || query.length <= 2) {
        return;
    }
    __WEBPACK_IMPORTED_MODULE_6__audioSearchClient_js__["a" /* default */].search(query).then((results) => {
        renderSearchResults(results);
    }).catch(console.error);
}
/**
 * Render search result items
 * @param {SearchResults} json
 */
function renderSearchResults(json) {
    const { results } = json;
    console.info(results);
    const resultsEl = document.querySelector('.search-results');
    if (results) {
        __WEBPACK_IMPORTED_MODULE_4__userData_js__["f" /* setSearchResults */](results);
        resultsEl.innerHTML = Object(__WEBPACK_IMPORTED_MODULE_1__components_searchResultList_js__["a" /* default */])(results);
    }
    else {
        resultsEl.innerHTML = '';
    }
}
/**
 * @param {Podcast|null} podcast
 */
function renderShowFeed(podcast) {
    const root = document.querySelector('.show-list');
    if (podcast) {
        podcast.items = __WEBPACK_IMPORTED_MODULE_4__userData_js__["c" /* getShowFeed */](`${podcast.id}`);
        root.innerHTML = Object(__WEBPACK_IMPORTED_MODULE_3__components_show_js__["a" /* default */])(podcast);
    }
    else {
        root.innerHTML = '';
    }
}
function renderUserShows() {
    const shows = __WEBPACK_IMPORTED_MODULE_4__userData_js__["d" /* getShows */]();
    const resultsEl = document.querySelector('.search-results');
    resultsEl.innerHTML = Object(__WEBPACK_IMPORTED_MODULE_2__components_userShowList_js__["a" /* default */])(shows);
}
// handle search result click
document.addEventListener('click', (event) => {
    if (!(event.target instanceof HTMLElement)) {
        return;
    }
    if (event.target.matches('header a')) {
        event.preventDefault();
        renderSearchResults({ results: null, page: 0, results_per_page: 0, total_results: 0 });
        renderShowFeed(null);
        renderUserShows();
    }
    if (event.target.matches('.search-result .podcast a')) {
        event.preventDefault();
        // @ts-ignore
        const feedUrl = event.target.href;
        const show = __WEBPACK_IMPORTED_MODULE_4__userData_js__["a" /* getSearchResult */](feedUrl);
        saveShow(show);
    }
    if (event.target.matches('.user-show .podcast a')) {
        event.preventDefault();
        // @ts-ignore
        const feedUrl = event.target.href;
        renderShowFeed(__WEBPACK_IMPORTED_MODULE_4__userData_js__["b" /* getShow */](feedUrl));
    }
    if (event.target.matches('.play[data-url]')) {
        [].slice.call(document.querySelectorAll('.playing')).forEach((i) => i.classList.remove('playing'));
        if (__WEBPACK_IMPORTED_MODULE_0__audioPlayer_js__["a" /* default */].play(event.target.getAttribute('data-url'))) {
            event.target.closest('.show-item').classList.add('playing');
        }
    }
});
/**
 * @param {Podcast} show
 */
function saveShow(show) {
    __WEBPACK_IMPORTED_MODULE_5__components_modal_js__["a" /* displayMessage */](`Saving ${show.title}`);
    __WEBPACK_IMPORTED_MODULE_6__audioSearchClient_js__["a" /* default */].getEpisodes(`${show.id}`)
        .then((episodes) => {
        __WEBPACK_IMPORTED_MODULE_4__userData_js__["e" /* saveShow */](show, episodes);
        __WEBPACK_IMPORTED_MODULE_5__components_modal_js__["b" /* hideMessage */]();
    });
}

/***/ }),
/* 3 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";

/* harmony default export */ __webpack_exports__["a"] = ({
    play(showMediaUrl) {
        const audio = document.querySelector('audio');
        if (audio.currentSrc !== showMediaUrl) {
            audio.src = showMediaUrl;
        }
        else if (audio.ended) {
            audio.currentTime = 0;
        }
        audio.paused ? audio.play() : audio.pause();
        return !audio.paused;
    }
});

/***/ }),
/* 4 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__showPoster_js__ = __webpack_require__(0);

/**
 * Render search result items
 * @param {Podcast[]} results
 * @return {string} html markup
 */
const component = (results) => {
    return results.map(podcast => {
        console.info({ podcast });
        const image = getImage(podcast);
        const artist = (podcast.network || { name: '' }).name;
        const { rss_url: feedUrl, title } = podcast;
        return `

        ${Object(__WEBPACK_IMPORTED_MODULE_0__showPoster_js__["a" /* default */])({ feedUrl, image, artist, title })}

    `.trim();
    }).join('\n');
};
/* unused harmony export component */

/* harmony default export */ __webpack_exports__["a"] = (component);
/**
 * @param {Podcast} pod
 */
function getImage(pod) {
    if (pod.image_files && pod.image_files.length) {
        return pod.image_files[0].file.thumb.url;
    }
    if (pod.image_urls) {
        return pod.image_urls.thumb;
    }
}

/***/ }),
/* 5 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__showPoster_js__ = __webpack_require__(0);

/**
 * Render search result items
 * @param {Podcast[]} userShows
 * @return {string} html markup
 */
const component = (userShows) => {
    return userShows.map(podcast => {
        const image = getImage(podcast);
        const artist = (podcast.network || { name: '' }).name;
        const { rss_url: feedUrl, title, } = podcast;
        return `

        ${Object(__WEBPACK_IMPORTED_MODULE_0__showPoster_js__["a" /* default */])({ feedUrl, image, artist, title })}

    `.trim();
    }).join('\n');
};
/* unused harmony export component */

/* harmony default export */ __webpack_exports__["a"] = (component);
/**
 * @param {Podcast} pod
 */
function getImage(pod) {
    if (pod.image_files && pod.image_files.length) {
        return pod.image_files[0].file.thumb.url;
    }
    if (pod.image_urls) {
        return pod.image_urls.thumb;
    }
}

/***/ }),
/* 6 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__episode_js__ = __webpack_require__(7);

/**
 *
 * @param {Podcast} show
 */
const component = (show) => {
    const image = getImage(show);
    return `

 ${show.title}

    ${show.items.map(__WEBPACK_IMPORTED_MODULE_0__episode_js__["a" /* default */]).join('\n')}

`.trim();
};
/* unused harmony export component */

/* harmony default export */ __webpack_exports__["a"] = (component);
/**
 * @param {Podcast} pod
 */
function getImage(pod) {
    if (pod.image_files && pod.image_files.length) {
        return pod.image_files[0].file.thumb.url;
    }
    if (pod.image_urls) {
        return pod.image_urls.thumb;
    }
}

/***/ }),
/* 7 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";

/* harmony default export */ __webpack_exports__["a"] = ((/** @type {Episode}*/ episode) => {
    const audio = episode.audio_files[0];
    return `

${episode.title}

${episode.description}

${getDaysAgoText(episode.date_created)} - ${audio.duration}

  `.trim();
});
function pad(number) {
    return `${number}`.padStart(2, '0');
}
function getDaysAgoText(dateString) {
    const msSincePublished = Date.now() - Date.parse(dateString);
    const daysAgo = Math.floor(msSincePublished / (24 * 60 * 60 * 1000));
    if (daysAgo === 0)
        return 'Today';
    if (daysAgo === 1)
        return 'Yesterday';
    return `${daysAgo} days ago`;
}

/***/ }),
/* 8 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";

const SHOWS = 'pod_shows';
const SEARCH_RESULTS = 'search_results';
/**
 *
 * @param {Podcast} showData
 * @param {Episode[]} items
 */
const saveShow = (showData, items) => {
    const shows = getShows();
    const show = getShow(showData.rss_url);
    if (show) {
        // we already have show - update?
        console.warn('show already in list...');
    }
    else {
        shows.push(showData);
    }
    localStorage.setItem(`${showData.id}`, JSON.stringify(items));
    localStorage.setItem(SHOWS, JSON.stringify(shows));
};
/* harmony export (immutable) */ __webpack_exports__["e"] = saveShow;

/**
 * @return {Podcast[]}
 */
const getShows = () => {
    const showData = localStorage.getItem(SHOWS);
    return showData ? JSON.parse(showData) : [];
};
/* harmony export (immutable) */ __webpack_exports__["d"] = getShows;

/**
 * @return {Podcast}
 */
const getShow = (feedUrl) => {
    const shows = getShows();
    return shows.find((s) => s.rss_url === feedUrl);
};
/* harmony export (immutable) */ __webpack_exports__["b"] = getShow;

/**
 * @param {string} id
 * @return {Episode[]}
 */
const getShowFeed = (id) => {
    const items = JSON.parse(localStorage.getItem(`${id}`) || '[]');
    return items;
};
/* harmony export (immutable) */ __webpack_exports__["c"] = getShowFeed;

/**
 * @param {Podcast[]} results
 */
const setSearchResults = (results) => {
    const dataStr = JSON.stringify(results || []);
    localStorage.setItem(SEARCH_RESULTS, dataStr);
};
/* harmony export (immutable) */ __webpack_exports__["f"] = setSearchResults;

/**
 * @param {string} feedUrl
 * @returns {Podcast}
 */
const getSearchResult = (feedUrl) => {
    /** @type {Podcast[]} */
    const results = JSON.parse(localStorage.getItem(SEARCH_RESULTS) || '[]');
    return results.find(pod => pod.rss_url === feedUrl);
};
/* harmony export (immutable) */ __webpack_exports__["a"] = getSearchResult;

/***/ }),
/* 9 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";

/** @type {HTMLElement} */
const modal = document.querySelector('.modal');
const displayMessage = (message, close) => {
    const messageEl = modal.querySelector('.modal__message');
    messageEl.innerHTML = message;
    modal.style.display = 'block';
};
/* harmony export (immutable) */ __webpack_exports__["a"] = displayMessage;

const hideMessage = () => {
    displayMessage('');
    modal.style.display = 'none';
};
/* harmony export (immutable) */ __webpack_exports__["b"] = hideMessage;

/***/ }),
/* 10 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__config_js__ = __webpack_require__(1);

// based on https://github.com/popuparchive/audiosearch-client-node/blob/master/index.js

__WEBPACK_IMPORTED_MODULE_0__config_js__["a" /* default */].get('token');
const host = __WEBPACK_IMPORTED_MODULE_0__config_js__["a" /* default */].get.bind(null, 'audio_service');
function authorize() {
    const tokenService = __WEBPACK_IMPORTED_MODULE_0__config_js__["a" /* default */].get('token_service');
    return fetch(`${tokenService}/token`).then(res => res.json()).then((res) => {
        console.log('Got access token...', res);
        __WEBPACK_IMPORTED_MODULE_0__config_js__["a" /* default */].set('token', res.access_token);
        return res.access_token;
    });
}
function base64Encode(str) {
    return btoa(str);
}
function get(path) {
    var url = `${host()}/api/${path}`;
    var options = {
        method: 'GET',
        headers: {
            'Authorization': `Bearer ${__WEBPACK_IMPORTED_MODULE_0__config_js__["a" /* default */].get('token')}`,
            'User-Agent': 'request'
        }
    };
    if (__WEBPACK_IMPORTED_MODULE_0__config_js__["a" /* default */].get('token')) {
        return fetch(url, options).then(res => res.json());
    }
    else {
        return authorize().then(() => get(path));
    }
}
class AudioSearchClient {
    /**
     * @param {string} query
     * @returns {Promise<SearchResults>}
     * @memberof AudioSearchClient
     */
    search(query) {
        const timer = 'audioSearch';
        console.time(timer);
        return get(`search/shows/${encodeURI(query)}`)
            .then(data => {
            console.timeEnd(timer);
            return data;
        });
    }
    /**
     * @param {string} show_id
     * @returns {Promise<Episode[]>}
     * @memberof AudioSearchClient
     */
    getEpisodes(show_id) {
        const timer = 'getEpisodes';
        console.time(timer);
        return get(`shows/${show_id}/episodes`)
            .then(data => {
            console.timeEnd(timer);
            return data;
        });
    }
}
/* harmony default export */ __webpack_exports__["a"] = (new AudioSearchClient());

/***/ })
/******/ ]);<commit_msg>remove bundle.js<commit_after><|endoftext|>