<commit_before>angular.module('radar')
.factory('MarkerFactory', function() {
  var markerObj = {};
  var markers = [];

  //filters is an object with properties popularity, category, distance, and keyword
  markerObj.placeMarkers = function(map, events, callback) {

    var bounds = new google.maps.LatLngBounds();

    if (events.length === 0) {
      return;
    }

    // create new markers for all events
    createMarkers(map, events, markers, bounds);

    map.fitBounds(bounds);

    if (events.length) {
      map.setZoom(14);
    }

    // var ratings = event.ratings;
    callback(markers);
  };
  //not using other above function because no callback is needed
  markerObj.filterMarkers = function(map, objFilters, filters) {
    // debugger;
    // remove all existing markers
    clearMarkers();

    var bounds = new google.maps.LatLngBounds();

    var events = objFilters.events;
    if (filters) {
      //filter.popularity is a number
      if (filters.popularity) {
        events = filterPopularity(events, filters.popularity);
      }
      //filter.category is a string
      if (filters.category) {
        events = filterCategory(events, filters.category);
      }
      //filter.distance is a number in miles
      if (filters.distance) {
        events = filterDistance(events, objFilters.location, filters.distance);
      }
      //filters.keyword is an array of stringed keywords
      if (filters.keywords) {
        var temp = filterKeyword(events, filters.keywords);
        if (temp.foundMatch) {
          events = temp.results;
        } else {
          events = [];
          //return that the keywords do not match any event
        }
      }
      //filters.cost is an object with lowEnd and highEnd properties containing a number
      if (filters.cost) {
        events = filterCost(events, filters.cost.lowEnd, filters.cost.highEnd);
      }
      //filters.time is an object with new, startTime, and endTime as a boolean, string, and string, respectively
      //The string must be capable of being parsed by Date.parse()
      if (filters.time.now || filters.time.startTime || filters.time.endTime) {
        events = filterTime(events, filters.time.now, filters.time.startTime, filters.time.endTime);
      }
      console.log("NEW EVENTS", events);
    }

    createMarkers(map, events, markers, bounds);

    map.fitBounds(bounds);

    if (events.length) {
      map.setZoom(14);
    }
  };

/********************* HELPER FUNCTIONS *********************/

  var createMarkers = function(map, events, markers, bounds) {
    for (var i = 0; i < events.length; i++) {
      var event = events[i];
      var position = new google.maps.LatLng(event.lat, event.lng);

      markers.push(new RichMarker({
        map: map,
        position: position,
        draggable: false,
        content: '
Rich
'
      }));

      bounds.extend(position);
    }
  };

  //Removes all markers on the map
  var clearMarkers = function() {
    for (var i = 0; i < markers.length; i++) {
      markers[i].setMap(null);
    }
  };

  var filterPopularity = function(events, popularity) {
    var results = [];
    for (var i = 0; i < events.length; i++) {
      if (events[i].popularity >= popularity) {
        results.push(events[i]);
      }
    }
    return results;
  };

  var filterCategory = function(events, category) {
    var results = [];
    for (var i = 0; i < events.length; i++) {
      if (events[i].category === category) {
        results.push(events[i]);
      }
    }
    return results;
  };

  var filterDistance = function(events, userLocation, distance) {
    var results = [];
    var parameters = latitudeLongitudeToDistanceConverter(userLocation.lat, userLocation.lng, distance);
    for (var i = 0; i < events.length; i++) {
      if (withinCoordinates(events[i], userLocation, parameters)) {
        results.push(events[i]);
      }
    }
    return results;
  };

  var filterKeyword = function(events, keywords) {
    var results = [];
    var count = 0;
    for (var i = 0; i < events.length; i++) {
      var match = false;
      for (var j = 0; j < keywords.length; j++) {
        if (events[i].info.search(keywords[j]) !== -1) {
          console.log("MATCH");
          match = true;
          break;
        }
      }
      if (match) {
        results.push(events[i]);
        count++;
      }
    }
    if (count > 0) {
      return {'foundMatch': true, 'results': results};
    } else {
      return {'foundMatch': false};
    }
  };

  var filterCost = function(events, lowCost, highCost) {
    var results = [];
    for (var i = 0; i < events.length; i++) {
      console.log(lowCost, events[i].price, highCost);
      if (events[i].price >= lowCost && events[i].price <= highCost) {
        results.push(events[i]);
      }
    }
    return results;
  };

  //All time will be dealt in number of milliseconds since Jan 1, 1970
  var filterTime = function(events, now, startTime, endTime) {
    var results = [];
    var twoHoursInMilliseconds = 7200000;
    var start;
    var end;
    for (var i = 0; i < events.length; i++) {
      if (now) {
        start = Date.now();
        end = Date.now() + twoHoursInMilliseconds;
      } else {
        start = Date.parse(startTime);
        if (endTime) {
          end = Date.parse(endTime);
        } else {
          //If no end time is specified, then end time will be set to 3 a.m. of the next day
          var temp = new Date();
          temp.setDate(temp.getDate() + 1);
          end = temp.setHours(3, 0, 0, 0);
        }
      }
      if (events[i].endTime >= start && events[i].startTime <= end) {
        results.push(events[i]);
      }
    }
    return results;
  };

  var latitudeLongitudeToDistanceConverter = function(lat, lng, d) {

    Number.prototype.toRadians = function() {
      return this * Math.PI / 180;
    };
    Number.prototype.toDegrees = function() {
      return this * 180 / Math.PI;
    };

    //Radius of Earth in miles
    var R = 3959;

    //Converts degrees to radians
    var lat1 = lat.toRadians();
    var lng1 = lng.toRadians();

    //find second latitude from 0º clockwise from North
    var lat2North = Math.asin(Math.sin(lat1) * Math.cos(d/R) + Math.cos(lat1) * Math.sin(d/R) * Math.cos(0));

    //find second longitude from 90º clockwise from North (needs lat2East to find second longitude)
    var lat2East = Math.asin(Math.sin(lat1) * Math.cos(d/R) + Math.cos(lat1) * Math.sin(d/R) * Math.cos(Math.PI / 2));
    var lng2East = lng1 + Math.atan2(Math.sin(Math.PI / 2) * Math.sin(d/R) * Math.cos(lat1), Math.cos(d/R) - Math.sin(lat1) * Math.sin(lat2East));

    // var Δx = x2 - x1;
    // var Δy = y2 - y1;

    // //Haversine formula to find greatest circle distance between two points
    // var a = Math.sin(Δx/2) * Math.sin(Δx/2) + Math.cos(x1) * Math.cos(x2) * Math.sin(Δy/2) * Math.sin(Δy/2);
    // var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    // var d = R * c;

    return {'north': lat2North.toDegrees() - lat, 'east': lng2East.toDegrees() - lng};
  };

  var withinCoordinates = function(events, userLocation, parameters) {
    if (events.lat <= userLocation.lat + parameters.north
      && events.lat >= userLocation.lat - parameters.north
      && events.lng <= userLocation.lng + parameters.east
      && events.lng >= userLocation.lng - parameters.east) {
      return true;
    }
    return false;
  };

  return markerObj;
});

<commit_msg>builds richmarkers markup based on event properties<commit_after>angular.module('radar')
.factory('MarkerFactory', function() {
  var markerObj = {};
  var markers = [];

  //filters is an object with properties popularity, category, distance, and keyword
  markerObj.placeMarkers = function(map, events, callback) {

    var bounds = new google.maps.LatLngBounds();

    if (events.length === 0) {
      return;
    }

    // create new markers for all events
    createMarkers(map, events, markers, bounds);

    if (events.length) {
      map.setZoom(14);
    }

    // var ratings = event.ratings;
    callback(markers);
  };
  //not using other above function because no callback is needed
  markerObj.filterMarkers = function(map, objFilters, filters) {
    // debugger;
    // remove all existing markers
    clearMarkers();

    var bounds = new google.maps.LatLngBounds();

    var events = objFilters.events;
    if (filters) {
      //filter.popularity is a number
      if (filters.popularity) {
        events = filterPopularity(events, filters.popularity);
      }
      //filter.category is a string
      if (filters.category) {
        events = filterCategory(events, filters.category);
      }
      //filter.distance is a number in miles
      if (filters.distance) {
        events = filterDistance(events, objFilters.location, filters.distance);
      }
      //filters.keyword is an array of stringed keywords
      if (filters.keywords) {
        var temp = filterKeyword(events, filters.keywords);
        if (temp.foundMatch) {
          events = temp.results;
        } else {
          events = [];
          //return that the keywords do not match any event
        }
      }
      //filters.cost is an object with lowEnd and highEnd properties containing a number
      if (filters.cost) {
        events = filterCost(events, filters.cost.lowEnd, filters.cost.highEnd);
      }
      //filters.time is an object with new, startTime, and endTime as a boolean, string, and string, respectively
      //The string must be capable of being parsed by Date.parse()
      if (filters.time.now || filters.time.startTime || filters.time.endTime) {
        events = filterTime(events, filters.time.now, filters.time.startTime, filters.time.endTime);
      }
      console.log("NEW EVENTS", events);
    }

    createMarkers(map, events, markers, bounds);

    map.fitBounds(bounds);

    if (events.length) {
      map.setZoom(14);
    }
  };

/********************* HELPER FUNCTIONS *********************/

  var createMarkers = function(map, events, markers, bounds) {
    var timeNow = Date.now();
    var happeningNow = '';
    var eventCategory = '';
    var popular = '';
    var markup = '';

    for (var i = 0; i < events.length; i++) {
      var event = events[i];
      var position = new google.maps.LatLng(event.lat, event.lng);

      // add 'happening-now' class if event is happening right now
      if (event.startTime < timeNow && timeNow < event.endTime) {
        happeningNow = 'happening-now ';
      }

      // add category and popularity classes to marker
      eventCategory = 'category-' + event.category + ' ';
      popularity = 'popularity-' + event.popularity + ' ';

      // build marker markup
      markup =
        '
O
';

      markers.push(new RichMarker({
        map: map,
        position: position,
        draggable: false,
        content: markup
      }));
    }
  };

  //Removes all markers on the map
  var clearMarkers = function() {
    for (var i = 0; i < markers.length; i++) {
      markers[i].setMap(null);
    }
  };

  var filterPopularity = function(events, popularity) {
    var results = [];
    for (var i = 0; i < events.length; i++) {
      if (events[i].popularity >= popularity) {
        results.push(events[i]);
      }
    }
    return results;
  };

  var filterCategory = function(events, category) {
    var results = [];
    for (var i = 0; i < events.length; i++) {
      if (events[i].category === category) {
        results.push(events[i]);
      }
    }
    return results;
  };

  var filterDistance = function(events, userLocation, distance) {
    var results = [];
    var parameters = latitudeLongitudeToDistanceConverter(userLocation.lat, userLocation.lng, distance);
    for (var i = 0; i < events.length; i++) {
      if (withinCoordinates(events[i], userLocation, parameters)) {
        results.push(events[i]);
      }
    }
    return results;
  };

  var filterKeyword = function(events, keywords) {
    var results = [];
    var count = 0;
    for (var i = 0; i < events.length; i++) {
      var match = false;
      for (var j = 0; j < keywords.length; j++) {
        if (events[i].info.search(keywords[j]) !== -1) {
          console.log("MATCH");
          match = true;
          break;
        }
      }
      if (match) {
        results.push(events[i]);
        count++;
      }
    }
    if (count > 0) {
      return {'foundMatch': true, 'results': results};
    } else {
      return {'foundMatch': false};
    }
  };

  var filterCost = function(events, lowCost, highCost) {
    var results = [];
    for (var i = 0; i < events.length; i++) {
      console.log(lowCost, events[i].price, highCost);
      if (events[i].price >= lowCost && events[i].price <= highCost) {
        results.push(events[i]);
      }
    }
    return results;
  };

  //All time will be dealt in number of milliseconds since Jan 1, 1970
  var filterTime = function(events, now, startTime, endTime) {
    var results = [];
    var twoHoursInMilliseconds = 7200000;
    var start;
    var end;
    for (var i = 0; i < events.length; i++) {
      if (now) {
        start = Date.now();
        end = Date.now() + twoHoursInMilliseconds;
      } else {
        start = Date.parse(startTime);
        if (endTime) {
          end = Date.parse(endTime);
        } else {
          //If no end time is specified, then end time will be set to 3 a.m. of the next day
          var temp = new Date();
          temp.setDate(temp.getDate() + 1);
          end = temp.setHours(3, 0, 0, 0);
        }
      }
      if (events[i].endTime >= start && events[i].startTime <= end) {
        results.push(events[i]);
      }
    }
    return results;
  };

  var latitudeLongitudeToDistanceConverter = function(lat, lng, d) {

    Number.prototype.toRadians = function() {
      return this * Math.PI / 180;
    };
    Number.prototype.toDegrees = function() {
      return this * 180 / Math.PI;
    };

    //Radius of Earth in miles
    var R = 3959;

    //Converts degrees to radians
    var lat1 = lat.toRadians();
    var lng1 = lng.toRadians();

    //find second latitude from 0º clockwise from North
    var lat2North = Math.asin(Math.sin(lat1) * Math.cos(d/R) + Math.cos(lat1) * Math.sin(d/R) * Math.cos(0));

    //find second longitude from 90º clockwise from North (needs lat2East to find second longitude)
    var lat2East = Math.asin(Math.sin(lat1) * Math.cos(d/R) + Math.cos(lat1) * Math.sin(d/R) * Math.cos(Math.PI / 2));
    var lng2East = lng1 + Math.atan2(Math.sin(Math.PI / 2) * Math.sin(d/R) * Math.cos(lat1), Math.cos(d/R) - Math.sin(lat1) * Math.sin(lat2East));

    // var Δx = x2 - x1;
    // var Δy = y2 - y1;

    // //Haversine formula to find greatest circle distance between two points
    // var a = Math.sin(Δx/2) * Math.sin(Δx/2) + Math.cos(x1) * Math.cos(x2) * Math.sin(Δy/2) * Math.sin(Δy/2);
    // var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    // var d = R * c;

    return {'north': lat2North.toDegrees() - lat, 'east': lng2East.toDegrees() - lng};
  };

  var withinCoordinates = function(events, userLocation, parameters) {
    if (events.lat <= userLocation.lat + parameters.north
      && events.lat >= userLocation.lat - parameters.north
      && events.lng <= userLocation.lng + parameters.east
      && events.lng >= userLocation.lng - parameters.east) {
      return true;
    }
    return false;
  };

  return markerObj;
});

<|endoftext|>


<commit_before>window.hwView = {
	subjects: {},
	loadCount: 0,
	swapOrder: false
};

window.hwView.addEventToList = function(ev, list) {
	var tag = window.utils.getPrefix(ev.name);
	var name = ev.name.split(" ");
	name.splice(0, 1);
	name = name.join(" ");
	var done = (ev.done == 1 ? true : false);

	if (name.trim() == "") {
		return;
	}

	var $item = $('

');
		if (done) {
			$item.addClass("hwView-done");
		}
		var $name = $('

');
			$name.text(name);
		// append comes later

		var $lineTwo = $('

');
			var $tag = $('');
				$tag.addClass("first-word");
				if (tag.toLowerCase() == "read") {
					tag = tag + "ing";
				}
				$tag.addClass(window.utils.getPrefixClass(tag));
				$tag.text(tag);
			$lineTwo.append($tag);

			var $subject = $('');
				$subject.text(" in " + window.hwView.subjects[ev.subject].name);
			$lineTwo.append($subject);

			var $due = $('');
				var keyword = "due";
				if (tag.toLowerCase() == "test" || tag.toLowerCase() == "exam" || tag.toLowerCase() == "midterm" || tag.toLowerCase() == "quiz" || tag.toLowerCase() == "ica" || tag.toLowerCase() == "lab") {
					keyword = "on";
				}
				$due.text(" " + keyword + " " + window.utils.formatDate_pretty(moment(ev.due).add(1, "day").toDate())); // timezones. and off-by-one errors.
			$lineTwo.append($due);
		// append comes later

		if (window.hwView.swapOrder) {
			$item.append($lineTwo);
			$item.append($name);
		} else {
			$item.append($name);
			$item.append($lineTwo);
		}

	$(".hwView-" + list + " ul").append($item);
};

window.hwView.loadList = function(date, list, callback) {
	for (var subjectIndex in window.hwView.subjects) {
		window.api.get("planner/events/get/" + window.utils.formatDate_api(date) + "/" + subjectIndex, function(data) {
			var ev = data.events;
			window.hwView.loadStep();
			if (ev.length == 0) {
				return;
			}
			for (var evIndex in ev) {
				var evObj = {
					name: ev[evIndex].text,
					due: new Date(data.date),
					subject: ev[evIndex].sectionIndex,
					done: ev[evIndex].done
				};
				window.hwView.addEventToList(evObj, list);
			};
		});
	}
};

window.hwView.loadSubjects = function(callback) {
	window.hwView.subjects = {};
	window.api.get("planner/sections/get/", function(data) {
		for (var i = 0; i < data.sections.length; i++) {
			var itm = data.sections[i];
			window.hwView.subjects[itm.sectionIndex] = itm;
		};
		callback(data.sections);
	});
};

window.hwView.findNextDay = function(offset) {
	var retVal = moment(); //moment().add("days", offset);
	if (retVal.day() == 6) {
		// don't start on Saturday
		retVal.add(1, "day");
	}
	for (var i = 0; i < offset; i++) {
		retVal.add(1, "day"); //add a day
		// is it a Saturday?
		if (retVal.day() == 6) {
			retVal.add(2, "day"); // skip the weekend
		}
	}
	return retVal.toDate();
};

window.hwView.loadStep = function() {
	window.hwView.loadCount += 1;
	if (window.hwView.loadCount >= (1 + (14 * Object.keys(window.hwView.subjects).length))) {
		window.page.hideLoading();
		if ($(".hwView-tomorrow ul").text() == "" && $(".hwView-soon ul").text() == "" && $(".hwView-longterm ul").text() == "") {
			// empty!
			alert("You don't have any homework in your planner! Click on the Planner tab and type in your homework. Once you've written some assignments in, come back here.");
		}
	}
};

window.hwView.loadEvents = function(callback) {
	window.hwView.loadSubjects(function(data) {
		window.hwView.loadStep();
		window.hwView.loadList(window.hwView.findNextDay(1), "tomorrow", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(2), "soon", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(3), "soon", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(4), "soon", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(5), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(6), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(7), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(8), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(9), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(10), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(11), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(12), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(13), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(14), "longterm", function() {

		});
	});
	callback();
};

$(document).ready(function() {
	$("#hwView").on("tabOpened", function() {
		window.page.showLoading();
		window.hwView.loadCount = 0;
		// clear lists
		$(".hwView-tomorrow ul").text("");
		$(".hwView-soon ul").text("");
		$(".hwView-longterm ul").text("");
		// special case for checking on Friday, Saturday, or Sunday
		if (moment().day() == 0 || moment().day() == 5 || moment().day() == 6) {
			$(".tomorrow-or-monday").text("Monday"); // the part that makes it show Monday stuff is in findNextDay().
		} else {
			$(".tomorrow-or-monday").text("tomorrow");
		}
		window.prefs.get("name-subj", function(val) {
			window.hwView.swapOrder = (val == "1");
			window.hwView.loadEvents(function() {

			});
		});
	});
});<commit_msg>added no colr hopefully?<commit_after>window.hwView = {
	subjects: {},
	loadCount: 0,
	swapOrder: false
};

window.hwView.addEventToList = function(ev, list) {
	var tag = window.utils.getPrefix(ev.name);
	var name = ev.name.split(" ");
	name.splice(0, 1);
	name = name.join(" ");
	var done = (ev.done == 1 ? true : false);

	if (name.trim() == "") {
		return;
	}

	var $item = $('

');
		if (done) {
			$item.addClass("hwView-done");
		}
		var $name = $('

');
			$name.text(name);
		// append comes later

		var $lineTwo = $('

');
			var $tag = $('');
				$tag.addClass("first-word");
				if (tag.toLowerCase() == "read") {
					tag = tag + "ing";
				}
				if(window.hwView.clr) {
				} else {
					$tag.addClass(window.utils.getPrefixClass(tag));
				}

				$tag.text(tag);
			$lineTwo.append($tag);

			var $subject = $('');
				$subject.text(" in " + window.hwView.subjects[ev.subject].name);
			$lineTwo.append($subject);

			var $due = $('');
				var keyword = "due";
				if (tag.toLowerCase() == "test" || tag.toLowerCase() == "exam" || tag.toLowerCase() == "midterm" || tag.toLowerCase() == "quiz" || tag.toLowerCase() == "ica" || tag.toLowerCase() == "lab") {
					keyword = "on";
				}
				$due.text(" " + keyword + " " + window.utils.formatDate_pretty(moment(ev.due).add(1, "day").toDate())); // timezones. and off-by-one errors.
			$lineTwo.append($due);
		// append comes later

		if (window.hwView.swapOrder) {
			$item.append($lineTwo);
			$item.append($name);
		} else {
			$item.append($name);
			$item.append($lineTwo);
		}

	$(".hwView-" + list + " ul").append($item);
};

window.hwView.loadList = function(date, list, callback) {
	for (var subjectIndex in window.hwView.subjects) {
		window.api.get("planner/events/get/" + window.utils.formatDate_api(date) + "/" + subjectIndex, function(data) {
			var ev = data.events;
			window.hwView.loadStep();
			if (ev.length == 0) {
				return;
			}
			for (var evIndex in ev) {
				var evObj = {
					name: ev[evIndex].text,
					due: new Date(data.date),
					subject: ev[evIndex].sectionIndex,
					done: ev[evIndex].done
				};
				window.hwView.addEventToList(evObj, list);
			};
		});
	}
};

window.hwView.loadSubjects = function(callback) {
	window.hwView.subjects = {};
	window.api.get("planner/sections/get/", function(data) {
		for (var i = 0; i < data.sections.length; i++) {
			var itm = data.sections[i];
			window.hwView.subjects[itm.sectionIndex] = itm;
		};
		callback(data.sections);
	});
};

window.hwView.findNextDay = function(offset) {
	var retVal = moment(); //moment().add("days", offset);
	if (retVal.day() == 6) {
		// don't start on Saturday
		retVal.add(1, "day");
	}
	for (var i = 0; i < offset; i++) {
		retVal.add(1, "day"); //add a day
		// is it a Saturday?
		if (retVal.day() == 6) {
			retVal.add(2, "day"); // skip the weekend
		}
	}
	return retVal.toDate();
};

window.hwView.loadStep = function() {
	window.hwView.loadCount += 1;
	if (window.hwView.loadCount >= (1 + (14 * Object.keys(window.hwView.subjects).length))) {
		window.page.hideLoading();
		if ($(".hwView-tomorrow ul").text() == "" && $(".hwView-soon ul").text() == "" && $(".hwView-longterm ul").text() == "") {
			// empty!
			alert("You don't have any homework in your planner! Click on the Planner tab and type in your homework. Once you've written some assignments in, come back here.");
		}
	}
};

window.hwView.loadEvents = function(callback) {
	window.hwView.loadSubjects(function(data) {
		window.hwView.loadStep();
		window.hwView.loadList(window.hwView.findNextDay(1), "tomorrow", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(2), "soon", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(3), "soon", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(4), "soon", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(5), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(6), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(7), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(8), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(9), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(10), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(11), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(12), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(13), "longterm", function() {

		});
		window.hwView.loadList(window.hwView.findNextDay(14), "longterm", function() {

		});
	});
	callback();
};

$(document).ready(function() {
	$("#hwView").on("tabOpened", function() {
		window.page.showLoading();
		window.hwView.loadCount = 0;
		// clear lists
		$(".hwView-tomorrow ul").text("");
		$(".hwView-soon ul").text("");
		$(".hwView-longterm ul").text("");
		// special case for checking on Friday, Saturday, or Sunday
		if (moment().day() == 0 || moment().day() == 5 || moment().day() == 6) {
			$(".tomorrow-or-monday").text("Monday"); // the part that makes it show Monday stuff is in findNextDay().
		} else {
			$(".tomorrow-or-monday").text("tomorrow");
		}
		window.prefs.get("name-subj", function(val) {
			window.hwView.swapOrder = (val == "1");
			window.prefs.get("titleclr"), function(val) {
				window.hwView.clr = (val == "1");
				window.hwView.loadEvents(function() {
				});
			}

		});
	});
});
<|endoftext|>


<commit_before>'use strict';

var config = require('config');

var serverStatus = require('../status');
var database = require('../database');
var isValidName = require('../validName');
var validateURL = require('../validURL');
var normalizeURL = require('../normalizeURL');
var url = require('url');
var path = require('path');
var GithubClient = require('github');
var request = require('request');

var memcached = require('../memcached');

function isOwner (packageName, token, callback) {
    if (!token) {
        return callback(null, false);
    }

    var githubClient = new GithubClient({
        version: '3.0.0'
    });
    githubClient.authenticate({
        type: 'oauth',
        token: token
    });

    database.getPackage(packageName, function (error, result) {
        if (error) {
            return callback({ status: 500, message: 'Database error' });
        }
        if (result.rows.length === 0) {
            return callback({ status: 404, message: 'Package not found' });
        }

        var pkg = result.rows[0];
        var urlParts = url.parse(pkg.url);
        var pathParts = urlParts.pathname.split('/');

        if (urlParts.hostname !== 'github.com' || pathParts.length !== 3 || pathParts[0] !== '') {
            return callback({ status: 501, message: 'Can only unregister packages hosted on GitHub.com' });
        }

        var owner = pathParts[1];
        var repo = path.basename(pathParts[2], '.git');

        function ghCheck (next) {
            return function (error) {
                if (error) {
                    if (error.code === 404) {
                        return next();
                    }

                    return callback({
                        status: error.code,
                        message: JSON.parse(error.message).message
                    });
                }
                callback(null, true);
            };
        }

        function getNewPath(path, cb) {
          var url = "http://github.com" + path;

          request.head(url, function(e, res) {
            if (e) cb(e);
            cb(null, res.req.path);
          });
        }

        getNewPath("/" + owner + "/" + repo, function (error, path) {
            if (error) {
                return callback({ status: 500, message: 'Error fetching GitHub repository path' });
            }

            var pathParts = path.split('/');
            var owner = pathParts[1];
            var repo = pathParts[2];

            githubClient.user.get({}, function (error, user) {
                if (error) {
                    return callback({ status: 500, message: 'Error fetching GitHub user info' });
                }
                githubClient.repos.getCollaborator({
                    user: owner,
                    repo: repo,
                    collabuser: user.login
                }, ghCheck(function () {
                    if (config.has('registryEditorsID')) {
                        githubClient.orgs.getTeamMember({
                            id: config.get('registryEditorsID'),
                            user: user.login
                        }, ghCheck(function () {
                            callback(null, false);
                        }));
                    } else {
                        callback(null, false);
                    }
                }));
            });
        });
    });
}

exports.remove = function (request, response) {
    /* jshint camelcase: false */
    var token = request.query.access_token;
    /* jshint camelcase: true */

    serverStatus.removePackage++;
    isOwner(request.params.name, token, function (error, result) {
        if (error) {
            serverStatus.errors.removePackageQuery++;
            return response.status(error.status).send(error.message);
        }
        if (!result) {
            serverStatus.errors.notAuthorized++;
            return response.status(403).send('Must be a collaborator on GitHub.com repository');
        }

        database.deletePackage(request.params.name, function (error) {
            if (error) {
                serverStatus.errors.removePackageQuery++;
                return response.status(500).send('Database error');
            }

            response.status(204).end();
        });
    });
};

exports.list = function (request, response) {
    response.setHeader('Content-Type', 'application/json');

    serverStatus.allPackages++;

    memcached.get('packages', function (error, value, key) {
        if (error) {
            serverStatus.errors.allPackagesQuery++;
            return response.status(500).send('Memcached read error');
        }

        if (value) {
            response.send(value);
        } else {
            database.getPackages(function (error, result) {
                if (error) {
                    serverStatus.errors.allPackagesQuery++;
                    return response.status(500).send('Database error');
                }

                memcached.set('packages', JSON.stringify(result.rows), function(error, value) {
                    if (error) {
                        serverStatus.errors.allPackagesQuery++;
                        return response.status(500).send('Memcached write error');
                    }

                    memcached.set('packages_count', String(result.rows.length), function(error, value) {
                        if (error) {
                            serverStatus.errors.allPackagesQuery++;
                            return response.status(500).send('Memcached write error');
                        }

                        return exports.list(request, response);
                    }, 600);
                }, 600);
            });
        }
    });
};

exports.stats = function (request, response) {
    memcached.get('packages_count', function (error, value, key) {
        if (error) {
            serverStatus.errors.allPackagesQuery++;
            return response.status(500).send('Memcached read error');
        }

        response.send(JSON.stringify({
            packages: parseInt(value, 10)
        }))
    });
};

exports.create = function (request, response) {
    var name = request.body.name;
    var url = normalizeURL(request.body.url);
    var validation = isValidName(name);

    serverStatus.createPackage++;

    if (validation.error) {
          serverStatus.errors.badName++;
          return response.status(400).send('Invalid Package Name. ' + validation.error);
    }

    validateURL(url, function(isValidURL) {
        if (isValidURL) {
            database.insertPackage(name, url, function (error) {
                if (error) {
                    serverStatus.errors.createPackageQuery++;
                    return response.status(403).send('Package already registered');
                }

                response.status(201).end();
            });
        } else {
            serverStatus.errors.badUrl++;
            response.status(400).send('Invalid URL');
        }
    });

};

exports.fetch = function (request, response) {
    serverStatus.getPackage++;
    database.getPackage(request.params.name, function (error, result) {
        if (error) {
            serverStatus.errors.getPackageQuery++;
            return response.status(500).send('Database error');
        }
        if (result.rows.length === 0) {
            serverStatus.errors.notFound++;
            return response.status(404).send('Package not found');
        }
        response.send(result.rows[0]);

        database.hit(request.params.name);
    });
};

exports.search = function (request, response) {
    serverStatus.searchPackage++;

    var name = request.params.name;
    var limit = Math.max(0, Math.min(1000, parseInt(request.query.limit, 10) || 30))

    database.searchPackages(name, limit, function (error, result) {
        if (error) {
            serverStatus.errors.searchPackageQuery++;
            return response.status(500).send('Database error');
        }
        response.send(result.rows);
    });
};
<commit_msg>Set appropriate mimetype for /stats endpoint<commit_after>'use strict';

var config = require('config');

var serverStatus = require('../status');
var database = require('../database');
var isValidName = require('../validName');
var validateURL = require('../validURL');
var normalizeURL = require('../normalizeURL');
var url = require('url');
var path = require('path');
var GithubClient = require('github');
var request = require('request');

var memcached = require('../memcached');

function isOwner (packageName, token, callback) {
    if (!token) {
        return callback(null, false);
    }

    var githubClient = new GithubClient({
        version: '3.0.0'
    });
    githubClient.authenticate({
        type: 'oauth',
        token: token
    });

    database.getPackage(packageName, function (error, result) {
        if (error) {
            return callback({ status: 500, message: 'Database error' });
        }
        if (result.rows.length === 0) {
            return callback({ status: 404, message: 'Package not found' });
        }

        var pkg = result.rows[0];
        var urlParts = url.parse(pkg.url);
        var pathParts = urlParts.pathname.split('/');

        if (urlParts.hostname !== 'github.com' || pathParts.length !== 3 || pathParts[0] !== '') {
            return callback({ status: 501, message: 'Can only unregister packages hosted on GitHub.com' });
        }

        var owner = pathParts[1];
        var repo = path.basename(pathParts[2], '.git');

        function ghCheck (next) {
            return function (error) {
                if (error) {
                    if (error.code === 404) {
                        return next();
                    }

                    return callback({
                        status: error.code,
                        message: JSON.parse(error.message).message
                    });
                }
                callback(null, true);
            };
        }

        function getNewPath(path, cb) {
          var url = "http://github.com" + path;

          request.head(url, function(e, res) {
            if (e) cb(e);
            cb(null, res.req.path);
          });
        }

        getNewPath("/" + owner + "/" + repo, function (error, path) {
            if (error) {
                return callback({ status: 500, message: 'Error fetching GitHub repository path' });
            }

            var pathParts = path.split('/');
            var owner = pathParts[1];
            var repo = pathParts[2];

            githubClient.user.get({}, function (error, user) {
                if (error) {
                    return callback({ status: 500, message: 'Error fetching GitHub user info' });
                }
                githubClient.repos.getCollaborator({
                    user: owner,
                    repo: repo,
                    collabuser: user.login
                }, ghCheck(function () {
                    if (config.has('registryEditorsID')) {
                        githubClient.orgs.getTeamMember({
                            id: config.get('registryEditorsID'),
                            user: user.login
                        }, ghCheck(function () {
                            callback(null, false);
                        }));
                    } else {
                        callback(null, false);
                    }
                }));
            });
        });
    });
}

exports.remove = function (request, response) {
    /* jshint camelcase: false */
    var token = request.query.access_token;
    /* jshint camelcase: true */

    serverStatus.removePackage++;
    isOwner(request.params.name, token, function (error, result) {
        if (error) {
            serverStatus.errors.removePackageQuery++;
            return response.status(error.status).send(error.message);
        }
        if (!result) {
            serverStatus.errors.notAuthorized++;
            return response.status(403).send('Must be a collaborator on GitHub.com repository');
        }

        database.deletePackage(request.params.name, function (error) {
            if (error) {
                serverStatus.errors.removePackageQuery++;
                return response.status(500).send('Database error');
            }

            response.status(204).end();
        });
    });
};

exports.list = function (request, response) {
    response.setHeader('Content-Type', 'application/json');

    serverStatus.allPackages++;

    memcached.get('packages', function (error, value, key) {
        if (error) {
            serverStatus.errors.allPackagesQuery++;
            return response.status(500).send('Memcached read error');
        }

        if (value) {
            response.send(value);
        } else {
            database.getPackages(function (error, result) {
                if (error) {
                    serverStatus.errors.allPackagesQuery++;
                    return response.status(500).send('Database error');
                }

                memcached.set('packages', JSON.stringify(result.rows), function(error, value) {
                    if (error) {
                        serverStatus.errors.allPackagesQuery++;
                        return response.status(500).send('Memcached write error');
                    }

                    memcached.set('packages_count', String(result.rows.length), function(error, value) {
                        if (error) {
                            serverStatus.errors.allPackagesQuery++;
                            return response.status(500).send('Memcached write error');
                        }

                        return exports.list(request, response);
                    }, 600);
                }, 600);
            });
        }
    });
};

exports.stats = function (request, response) {
    memcached.get('packages_count', function (error, value, key) {
        if (error) {
            serverStatus.errors.allPackagesQuery++;
            return response.status(500).send('Memcached read error');
        }

        response.setHeader('Content-Type', 'application/json');
        response.send(JSON.stringify({
            packages: parseInt(value, 10)
        }))
    });
};

exports.create = function (request, response) {
    var name = request.body.name;
    var url = normalizeURL(request.body.url);
    var validation = isValidName(name);

    serverStatus.createPackage++;

    if (validation.error) {
          serverStatus.errors.badName++;
          return response.status(400).send('Invalid Package Name. ' + validation.error);
    }

    validateURL(url, function(isValidURL) {
        if (isValidURL) {
            database.insertPackage(name, url, function (error) {
                if (error) {
                    serverStatus.errors.createPackageQuery++;
                    return response.status(403).send('Package already registered');
                }

                response.status(201).end();
            });
        } else {
            serverStatus.errors.badUrl++;
            response.status(400).send('Invalid URL');
        }
    });

};

exports.fetch = function (request, response) {
    serverStatus.getPackage++;
    database.getPackage(request.params.name, function (error, result) {
        if (error) {
            serverStatus.errors.getPackageQuery++;
            return response.status(500).send('Database error');
        }
        if (result.rows.length === 0) {
            serverStatus.errors.notFound++;
            return response.status(404).send('Package not found');
        }
        response.send(result.rows[0]);

        database.hit(request.params.name);
    });
};

exports.search = function (request, response) {
    serverStatus.searchPackage++;

    var name = request.params.name;
    var limit = Math.max(0, Math.min(1000, parseInt(request.query.limit, 10) || 30))

    database.searchPackages(name, limit, function (error, result) {
        if (error) {
            serverStatus.errors.searchPackageQuery++;
            return response.status(500).send('Database error');
        }
        response.send(result.rows);
    });
};
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	Schema = mongoose.Schema;

/**
 * Article Schema
 */
var ArticleSchema = new Schema({
	created: {
		type: Date,
		default: Date.now
	},
	moduleCode: {
		type: String,
		default: '',
		trim: true,
		required: 'Module Code cannot be blank'
	},
	pastLecturer: {
		type: [Schema.ObjectId],
		ref: 'VersionFaculty'
	},
	// pastTA: {
	// 	type: [Schema.ObjectId],
	// 	ref: 'Faculty'
	// },
	funFacts: {
		type: [Schema.ObjectId],
		ref: 'VersionString'
	},
	outstandingProj: {
		type: [Schema.ObjectId],
		ref: 'VersionProject'
	},
	others: {
		type: [Schema.ObjectId],
		ref: 'VersionString'
	},
	facebook: {
		type: [Schema.ObjectId],
		ref: 'VersionString'
	},
	homePage: {
		type: [Schema.ObjectId],
		ref: 'VersionString'
	},
	logo: {
		type: [Schema.ObjectId],
		ref: 'VersionString'
	}
});

mongoose.model('Article', ArticleSchema);
<commit_msg>changed pastTa model<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	Schema = mongoose.Schema;

/**
 * Article Schema
 */
var ArticleSchema = new Schema({
	created: {
		type: Date,
		default: Date.now
	},
	moduleCode: {
		type: String,
		default: '',
		trim: true,
		required: 'Module Code cannot be blank'
	},
	pastLecturer: {
		type: [Schema.ObjectId],
		ref: 'VersionFaculty'
	},
	// pastTA: {
	// 	type: [Schema.ObjectId],
	// 	ref: 'VersionFaculty'
	// },
	funFacts: {
		type: [Schema.ObjectId],
		ref: 'VersionString'
	},
	outstandingProj: {
		type: [Schema.ObjectId],
		ref: 'VersionProject'
	},
	others: {
		type: [Schema.ObjectId],
		ref: 'VersionString'
	},
	facebook: {
		type: [Schema.ObjectId],
		ref: 'VersionString'
	},
	homePage: {
		type: [Schema.ObjectId],
		ref: 'VersionString'
	},
	logo: {
		type: [Schema.ObjectId],
		ref: 'VersionString'
	}
});

mongoose.model('Article', ArticleSchema);
<|endoftext|>


<commit_before>

var ymdFormat = d3.time.format('%Y-%m-%d'),
    timeFormat = d3.time.format('%-I:%M %p'),
    monthFormat = d3.time.format('%B'),
    dayNumFormat = d3.time.format('%e'),
    dayNameFormat = d3.time.format('%A'),
    yearFormat = d3.time.format('%Y');

var chart = new d3Kit.Skeleton('#month-view', {
    margin: {top: 0, right: 0, bottom: 0, left: 0}
  })
  .autoResize('width')
  .autoResizeToAspectRatio(1);

var redraw = function(date) {

  if (Object.prototype.toString.call( date ) !== '[object Date]') {
    // not a date - chart size (from resize)
    return;
  }

  if (!chart.hasData()) {
    return;
  }

  var x = chart.getInnerWidth()/7;
  var y = chart.getInnerHeight()/7;
  var r = x/2;

  var g = chart.getRootG().selectAll('g')
    .data(function() {
      var start = d3.time.sunday.floor(date);

      while (date.getMonth() == start.getMonth() &&
             start.getDate() != 0) {
        start = d3.time.sunday.floor(new Date(start.getTime() - (24*60*60*1000)));
      }

      var end = d3.time.sunday.ceil(new Date(date.getFullYear(), date.getMonth()+1, 0));

      var days = d3.time.days(start, end);

      while (days.length < 42) {
        end = d3.time.sunday.ceil(new Date(end.getTime() + (24*60*60*1000)));
        days = d3.time.days(start, end);
      }

      return [days.slice(0, 7),
          days.slice(7, 14),
          days.slice(14, 21),
          days.slice(21, 28),
          days.slice(28, 35),
          days.slice(35, 42)];
    });

  g.exit().remove();

  g.enter()
    .append('g');

  g.attr('transform', function(d,i) {
    return 'translate('+r+', ' + i*y + ')';
  });

  var c = g.selectAll('circle.cal')
    .data(function(d) { return d; });

  c.exit().remove();

  c.enter()
      .append('circle')
      .classed('cal', true);

  c.classed('current', function(d) {
    if (ymdFormat(date) == ymdFormat(d)) {
      return true;
    }
    return false;
  })
  .classed('in-month', function(d) {
    if (monthFormat(date) == monthFormat(d)) {
      return true;
    }
    return false;
  })
  .attr('cx', function(d,i) { return i*x; })
  .attr('cy', r)
  .attr('r', r)
  .on('mouseover', function(d) {
    console.log(d);
    d3.select('#circle-data').text(JSON.stringify(d));
  });

  var txt = g.selectAll('text.cal').data(function(d) { return d; });

  txt.exit().remove();

  txt.enter()
    .append('text')
    .classed('cal', true);

  txt.classed('current', function(d) {
    if (ymdFormat(date) == ymdFormat(d)) {
      return true;
    }
    return false;
  })
  .classed('in-month', function(d) {
    if (monthFormat(date) == monthFormat(d)) {
      return true;
    }
    return false;
  })
  .attr('x', function(d,i) { return i*x; })
  .attr('y', r+(r/4))
  .attr('font-size', r)
  .attr('text-anchor', 'middle')
  .text(function(d) {
    return dayNumFormat(d);
  });
}

chart
  .on('resize', redraw)
  .on('data', redraw);

var textSvg = d3Kit.factory.createChart(
  {
    margin: {top: 0, right: 0, bottom: 0, left: 0},
    initialWidth: 0,
    initialHeight: 0
  },
  [],
  function(skel) {

    var pt = 1;

    skel.mixin({
      'text': function(d) {
        return d;
      }
    });

    var resize = function(dim) {
      redraw(skel.data());
    };

    var redraw = function() {
      var data = skel.data();

      if (Object.prototype.toString.call( data ) !== '[object Date]') {
        // not a date - chart size (from resize)
        return;
      }

      if (!skel.hasData()) {
        return;
      }

      var dispatch = skel.getDispatcher();

      var txt = skel.getRootG()
        .selectAll('text')
        .data([data]);

      txt.exit().remove();

      txt.enter()
        .append('text')
          .style('font-size', pt);

      txt.text(skel.text);

      //var div = d3.select('#time').node().getBoundingClientRect();
      var div = {width: skel.getInnerWidth(), height: skel.getInnerHeight()};
      var svg = txt.node().getBBox();

      // see how big the text can grow
      var checkedMax = false;
      while(svg.width
 div.width) {
        checkedMin = true;
        txt.style('font-size', pt--)
           .attr('y', pt-(pt*.25)); // take some for hanging chars
        svg = txt.node().getBBox();
      }

      // found the min
      if (checkedMin) {
        pt++;
      }

      skel.height(svg.height, true);

      txt.style('font-size', pt)
         .attr('y', pt-(pt*.25)); // take some for hanging chars
    };

    skel
      .autoResize('both')
      .on('resize', resize)
      .on('data', redraw);
  });

var time = new textSvg('#time').mixin({
  'text': function(d) {return timeFormat(d);}
});

var year = new textSvg('#year').mixin({
  'text': function(d) {return yearFormat(d);}
});

var day = new textSvg('#day').mixin({
  'text': function(d) {return dayNameFormat(d);}
});

var dateLong = new textSvg('#date').mixin({
  'text': function(d) {
    return dayNumFormat(d)+' '+monthFormat(d);}
});

function updateDate() {

  var date = new Date();

  time.data(date);
  year.data(date);
  day.data(date);
  dateLong.data(date);

  chart.data(date);

  d3.select('#footer').html(' Last refreshed at ' + d3.time.format.iso(new Date()));
}

updateDate();
setInterval(updateDate, 60000);

d3.xml('/api/v1/weather', "application/xml", function(err, xml) {

  console.log(err,xml);
  var rss = xml.getElementsByTagName('rss');
  var channel = rss[0].getElementsByTagName('channel');
  var items = channel[0].getElementsByTagName('item');

  var data = [];
  for(var i = 0; i < items.length; i++) {
    data.push(items[i]);
  }

  var p = d3.select('#weather').selectAll('p')
    .data(data.filter(function(d) {
      var str = d.getElementsByTagName('title')[0].childNodes[0].nodeValue;
      console.log(str);
      if (str.toLowerCase().indexOf('current weather') == -1 &&
          str.toLowerCase().indexOf('weather forecast') == -1) {
        return false;
      }
      return true;
    }));

  p.exit().remove();

  p.enter().append('p');

  p.html(function(d) {
  console.log(d);
    return d.getElementsByTagName('title')[0].childNodes[0].nodeValue + "
" +
      d.getElementsByTagName('description')[0].childNodes[0].nodeValue;
  });

});<commit_msg>remove unnecessary logging<commit_after>

var ymdFormat = d3.time.format('%Y-%m-%d'),
    timeFormat = d3.time.format('%-I:%M %p'),
    monthFormat = d3.time.format('%B'),
    dayNumFormat = d3.time.format('%e'),
    dayNameFormat = d3.time.format('%A'),
    yearFormat = d3.time.format('%Y');

var chart = new d3Kit.Skeleton('#month-view', {
    margin: {top: 0, right: 0, bottom: 0, left: 0}
  })
  .autoResize('width')
  .autoResizeToAspectRatio(1);

var redraw = function(date) {

  if (Object.prototype.toString.call( date ) !== '[object Date]') {
    // not a date - chart size (from resize)
    return;
  }

  if (!chart.hasData()) {
    return;
  }

  var x = chart.getInnerWidth()/7;
  var y = chart.getInnerHeight()/7;
  var r = x/2;

  var g = chart.getRootG().selectAll('g')
    .data(function() {
      var start = d3.time.sunday.floor(date);

      while (date.getMonth() == start.getMonth() &&
             start.getDate() != 0) {
        start = d3.time.sunday.floor(new Date(start.getTime() - (24*60*60*1000)));
      }

      var end = d3.time.sunday.ceil(new Date(date.getFullYear(), date.getMonth()+1, 0));

      var days = d3.time.days(start, end);

      while (days.length < 42) {
        end = d3.time.sunday.ceil(new Date(end.getTime() + (24*60*60*1000)));
        days = d3.time.days(start, end);
      }

      return [days.slice(0, 7),
          days.slice(7, 14),
          days.slice(14, 21),
          days.slice(21, 28),
          days.slice(28, 35),
          days.slice(35, 42)];
    });

  g.exit().remove();

  g.enter()
    .append('g');

  g.attr('transform', function(d,i) {
    return 'translate('+r+', ' + i*y + ')';
  });

  var c = g.selectAll('circle.cal')
    .data(function(d) { return d; });

  c.exit().remove();

  c.enter()
      .append('circle')
      .classed('cal', true);

  c.classed('current', function(d) {
    if (ymdFormat(date) == ymdFormat(d)) {
      return true;
    }
    return false;
  })
  .classed('in-month', function(d) {
    if (monthFormat(date) == monthFormat(d)) {
      return true;
    }
    return false;
  })
  .attr('cx', function(d,i) { return i*x; })
  .attr('cy', r)
  .attr('r', r)
  .on('mouseover', function(d) {
    console.log(d);
    d3.select('#circle-data').text(JSON.stringify(d));
  });

  var txt = g.selectAll('text.cal').data(function(d) { return d; });

  txt.exit().remove();

  txt.enter()
    .append('text')
    .classed('cal', true);

  txt.classed('current', function(d) {
    if (ymdFormat(date) == ymdFormat(d)) {
      return true;
    }
    return false;
  })
  .classed('in-month', function(d) {
    if (monthFormat(date) == monthFormat(d)) {
      return true;
    }
    return false;
  })
  .attr('x', function(d,i) { return i*x; })
  .attr('y', r+(r/4))
  .attr('font-size', r)
  .attr('text-anchor', 'middle')
  .text(function(d) {
    return dayNumFormat(d);
  });
}

chart
  .on('resize', redraw)
  .on('data', redraw);

var textSvg = d3Kit.factory.createChart(
  {
    margin: {top: 0, right: 0, bottom: 0, left: 0},
    initialWidth: 0,
    initialHeight: 0
  },
  [],
  function(skel) {

    var pt = 1;

    skel.mixin({
      'text': function(d) {
        return d;
      }
    });

    var resize = function(dim) {
      redraw(skel.data());
    };

    var redraw = function() {
      var data = skel.data();

      if (Object.prototype.toString.call( data ) !== '[object Date]') {
        // not a date - chart size (from resize)
        return;
      }

      if (!skel.hasData()) {
        return;
      }

      var dispatch = skel.getDispatcher();

      var txt = skel.getRootG()
        .selectAll('text')
        .data([data]);

      txt.exit().remove();

      txt.enter()
        .append('text')
          .style('font-size', pt);

      txt.text(skel.text);

      //var div = d3.select('#time').node().getBoundingClientRect();
      var div = {width: skel.getInnerWidth(), height: skel.getInnerHeight()};
      var svg = txt.node().getBBox();

      // see how big the text can grow
      var checkedMax = false;
      while(svg.width
 div.width) {
        checkedMin = true;
        txt.style('font-size', pt--)
           .attr('y', pt-(pt*.25)); // take some for hanging chars
        svg = txt.node().getBBox();
      }

      // found the min
      if (checkedMin) {
        pt++;
      }

      skel.height(svg.height, true);

      txt.style('font-size', pt)
         .attr('y', pt-(pt*.25)); // take some for hanging chars
    };

    skel
      .autoResize('both')
      .on('resize', resize)
      .on('data', redraw);
  });

var time = new textSvg('#time').mixin({
  'text': function(d) {return timeFormat(d);}
});

var year = new textSvg('#year').mixin({
  'text': function(d) {return yearFormat(d);}
});

var day = new textSvg('#day').mixin({
  'text': function(d) {return dayNameFormat(d);}
});

var dateLong = new textSvg('#date').mixin({
  'text': function(d) {
    return dayNumFormat(d)+' '+monthFormat(d);}
});

function updateDate() {

  var date = new Date();

  time.data(date);
  year.data(date);
  day.data(date);
  dateLong.data(date);

  chart.data(date);

  d3.select('#footer').html(' Last refreshed at ' + d3.time.format.iso(new Date()));
}

updateDate();
setInterval(updateDate, 60000);

d3.xml('/api/v1/weather', "application/xml", function(err, xml) {

  console.log('weather', err,xml);
  var rss = xml.getElementsByTagName('rss');
  var channel = rss[0].getElementsByTagName('channel');
  var items = channel[0].getElementsByTagName('item');

  var data = [];
  for(var i = 0; i < items.length; i++) {
    data.push(items[i]);
  }

  var p = d3.select('#weather').selectAll('p')
    .data(data.filter(function(d) {
      var str = d.getElementsByTagName('title')[0].childNodes[0].nodeValue;
      if (str.toLowerCase().indexOf('current weather') == -1 &&
          str.toLowerCase().indexOf('weather forecast') == -1) {
        return false;
      }
      return true;
    }));

  p.exit().remove();

  p.enter().append('p');

  p.html(function(d) {
    return d.getElementsByTagName('title')[0].childNodes[0].nodeValue + "
" +
      d.getElementsByTagName('description')[0].childNodes[0].nodeValue;
  });

});<|endoftext|>


<commit_before>var items=[
	{
		name:"Percent below poverty line",
		tables:"B17001_002E,B17001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [parseFloat(a[i][0])*100 / parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Median Household Income",
		tables:"B19013_001E",
		flip:true

	},{
		name:"Per capita income",
		tables:"B19301_001E",
		flip:true

	},{
		name:"Inequality",
		tables:"B19083_001E",
		stringRep:function(a){
			return  parseFloat(a,10).toPrecision(5);
		}
	},{
		name:"Avg Commute",
		tables:"B08131_001E,B08122_001E",
		transform: function(a) {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [parseFloat(a[i][0]) / parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Income Car Vs Trans",
		tables:"B08121_002E,B08121_004E",
		transform:function(a) {
			var b = [],i,ct,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [parseFloat(a[i][0]) - parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		},
		flip:true
	},{
		name:"Percent on foodstamps",
		tables:"B22007_002E,B22007_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [parseFloat(a[i][0])*100 / parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Population",
		tables:"B01001_001E"
	},{
		name:"Most Welsh (Welsh per 10,000)",
		tables:"B04001_093E,B04001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [parseFloat(a[i][0])*10000 / parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		},
		flip:true
	},{
		name:"LPM (Luxemburger Per Million)",
		tables:"B04001_054E,B04001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [parseFloat(a[i][0])*1000000 / parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		},
		flip:true
	},{
		name:"Gender Ratio (Men per 100 Women)",
		tables:"B01001_002E,B01001_026E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [parseFloat(a[i][0])*100 / parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Movement (Percent Moved in last year)",
		tables:"B07001_001E,B07001_017E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ (parseFloat(a[i][0])-parseFloat(a[i][1]))*100 / parseFloat(a[i][0]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Education (Didn't Graduate HS)",
		tables:"B06009_002E,B06009_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ parseFloat(a[i][0])*100 / parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Rent as Percentage of Income",
		tables:"B25071_001E"

	},{
		name:'Rooms per House',
		tables:"B25018_001E",
		stringRep:function(a){
			return  parseFloat(a,10).toPrecision(2);
		},
		flip:true
	},{
		name:"Age of Structures (years)",
		tables:"B25035_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			var currentYear = (new Date()).getFullYear();
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ currentYear-parseFloat(a[i][0]), a[i][1], a[i][2]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Houses Without Bathrooms (Per 10000)",
		tables:"B25048_003E,B25048_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ parseFloat(a[i][0])*10000 / parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Avg Hours Worked",
		tables:"B23020_001E",
		stringRep:function(a){
			return  parseFloat(a,10).toPrecision(4);
		}
	},{
		name:"Whitest",
		tables:"B02001_002E,B02001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ parseFloat(a[i][0])*10000/ parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Blackest",
		tables:"B02001_003E,B02001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ parseFloat(a[i][0])*10000/ parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Most Asian",
		tables:"B02001_005E,B02001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ parseFloat(a[i][0])*10000/ parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Most Native American",
		tables:"B02001_004E,B02001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ parseFloat(a[i][0])*10000/ parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Most Mixed Race",
		tables:"B02001_008E,B02001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ parseFloat(a[i][0])*10000/ parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Non Existent Nationalities (Czechoslovakian, Yugoslavian, and Soviet Union)",
		tables:"B04001_107E,B04001_032E,B04001_072E,B04001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ (parseFloat(a[i][0])+parseFloat(a[i][1])+parseFloat(a[i][2]))*100000/ parseFloat(a[i][3]), a[i][4], a[i][5]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	}
];
<commit_msg>more explicit numbers<commit_after>var items=[
	{
		name:"Percent below poverty line",
		tables:"B17001_002E,B17001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [parseFloat(a[i][0])*100 / parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Median Household Income",
		tables:"B19013_001E",
		flip:true

	},{
		name:"Per capita income",
		tables:"B19301_001E",
		flip:true

	},{
		name:"Inequality",
		tables:"B19083_001E",
		stringRep:function(a){
			return  parseFloat(a,10).toPrecision(5);
		}
	},{
		name:"Avg Commute",
		tables:"B08131_001E,B08122_001E",
		transform: function(a) {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [parseFloat(a[i][0]) / parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Income Car Vs Trans",
		tables:"B08121_002E,B08121_004E",
		transform:function(a) {
			var b = [],i,ct,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [parseFloat(a[i][0]) - parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		},
		flip:true
	},{
		name:"Percent on foodstamps",
		tables:"B22007_002E,B22007_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [parseFloat(a[i][0])*100 / parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Population",
		tables:"B01001_001E"
	},{
		name:"Most Welsh (Welsh per 10,000)",
		tables:"B04001_093E,B04001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [parseFloat(a[i][0])*10000 / parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		},
		flip:true
	},{
		name:"LPM (Luxemburger Per Million)",
		tables:"B04001_054E,B04001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [parseFloat(a[i][0])*1000000 / parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		},
		flip:true
	},{
		name:"Gender Ratio (Men per 100 Women)",
		tables:"B01001_002E,B01001_026E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [parseFloat(a[i][0])*100 / parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Movement (Percent Moved in last year)",
		tables:"B07001_001E,B07001_017E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ (parseFloat(a[i][0])-parseFloat(a[i][1]))*100 / parseFloat(a[i][0]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Education (Didn't Graduate HS)",
		tables:"B06009_002E,B06009_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ parseFloat(a[i][0])*100 / parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Rent as Percentage of Income",
		tables:"B25071_001E"

	},{
		name:'Rooms per House',
		tables:"B25018_001E",
		stringRep:function(a){
			return  parseFloat(a,10).toPrecision(2);
		},
		flip:true
	},{
		name:"Age of Structures (years)",
		tables:"B25035_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			var currentYear = (new Date()).getFullYear();
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ currentYear-parseFloat(a[i][0]), a[i][1], a[i][2]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Houses Without Bathrooms (Per 10000)",
		tables:"B25048_003E,B25048_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ parseFloat(a[i][0])*10000 / parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Avg Hours Worked",
		tables:"B23020_001E",
		stringRep:function(a){
			return  parseFloat(a,10).toPrecision(4);
		}
	},{
		name:"Whitest (White People per 10k)",
		tables:"B02001_002E,B02001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ parseFloat(a[i][0])*10000/ parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Blackest (Black People per 10k)",
		tables:"B02001_003E,B02001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ parseFloat(a[i][0])*10000/ parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Asians per 10K",
		tables:"B02001_005E,B02001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ parseFloat(a[i][0])*10000/ parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Native American per 10K",
		tables:"B02001_004E,B02001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ parseFloat(a[i][0])*10000/ parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Mixed Race People per 10K",
		tables:"B02001_008E,B02001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ parseFloat(a[i][0])*10000/ parseFloat(a[i][1]), a[i][2], a[i][3]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	},{
		name:"Non Existent Nationalities (Czechoslovakian, Yugoslavian, and Soviet Union per 100K)",
		tables:"B04001_107E,B04001_032E,B04001_072E,B04001_001E",
		transform:function(a)  {
			var b = [];
			var ct,i,len;
			for (i = 0,len=a.length; i < len; i++) {
				ct = [ (parseFloat(a[i][0])+parseFloat(a[i][1])+parseFloat(a[i][2]))*100000/ parseFloat(a[i][3]), a[i][4], a[i][5]];
				ct[0] = ct[0]|0;
				b.push(ct);
			}
			return b;
		}
	}
];
<|endoftext|>


<commit_before>;(function () {
/* jshint browser:true, evil:true */

// 1. create iframe pointing to script on jsconsole.com domain
// 2. create console object with: log, dir, etc?
// 3. console.log runs postMessage with json.stringified content
// 4. jsconsole.com/remote/?id.onMessage = send to server, and wait for response.

function sortci(a, b) {
  return a.toLowerCase() < b.toLowerCase() ? -1 : 1;
}

// from console.js
function stringify(o, simple) {
  var json = '', i, type = ({}).toString.call(o), parts = [], names = [];

  if (type === '[object String]') {
    json = '"' + o.replace(/\n/g, '\\n').replace(/"/g, '\\"') + '"';
  } else if (type === '[object Array]') {
    json = '[';
    for (i = 0; i < o.length; i++) {
      parts.push(stringify(o[i], simple));
    }
    json += parts.join(', ') + ']';
  } else if (type === '[object Object]') {
    json = '{';
    for (i in o) {
      names.push(i);
    }
    names.sort(sortci);
    for (i = 0; i < names.length; i++) {
      parts.push(stringify(names[i]) + ': ' + stringify(o[names[i] ], simple));
    }
    json += parts.join(', ') + '}';
  } else if (type === '[object Number]') {
    json = o+'';
  } else if (type === '[object Boolean]') {
    json = o ? 'true' : 'false';
  } else if (type === '[object Function]') {
    json = o.toString();
  } else if (o === null) {
    json = 'null';
  } else if (o === undefined) {
    json = 'undefined';
  } else if (simple === undefined) {
    json = type + '{\n';
    for (i in o) {
      names.push(i);
    }
    names.sort(sortci);
    for (i = 0; i < names.length; i++) {
      // safety from max stack
      parts.push(names[i] + ': ' + stringify(o[names[i]], true));
    }
    json += parts.join(',\n') + '\n}';
  } else {
    try {
      json = o+''; // should look like an object
    } catch (e) {}
  }
  return json;
}

function getRemoteScript() {
  var scripts = document.getElementsByTagName('script');
  var remoteScript = scripts[scripts.length-1];
  var re = /jsconsole\..*(:\d+)?\/js\/remote.js/;
  for (var i = 0; i < scripts.length; i++) {
    if (re.test(scripts[i].src)) {
      remoteScript = scripts[i];
      break;
    }
  }

  return remoteScript;
}

var last = getRemoteScript();

var lastSrc = last.getAttribute('src'),
    id = lastSrc.replace(/.*\?/, ''),
    protocol = /https?:\/\//.exec(lastSrc)[0],
    origin = protocol + lastSrc.substr(protocol.length).replace(/\/.*$/, ''),
    remoteWindow = null,
    queue = [],
    msgType = '';

var remoteFrame = document.createElement('iframe');
remoteFrame.style.display = 'none';
remoteFrame.src = origin + '/remote.html?' + id;

// an attempt to allow this code to be included in the head element
document.documentElement.appendChild(remoteFrame);

window.addEventListener('message', function (event) {
  if (event.origin !== origin) {
    return;
  }

  // this isn't for us
  if (typeof event.data !== 'string') {
    return;
  }

  // eval the event.data command
  try {
    if (event.data.indexOf('console.log') === 0) {
      eval('remote.echo(' + event.data.match(/console.log\((.*)\);?/)[1] + ', "' + event.data + '", true)');
    } else {
      // must be undefined to work
      remote.echo(eval(event.data), event.data, undefined);
    }
  } catch (e) {
    _console.log(e.stack, event);
    remote.error(e, event.data);
  }
}, false);

var timers = {}; // timers for console.time and console.timeEnd

var remote = {
  log: function () {
    // var argsObj = stringify(arguments.length === 1 ? arguments[0] : [].slice.call(arguments, 0));
    var response = [];
    [].forEach.call(arguments, function (args) {
      response.push(stringify(args, true));
    });

    var msg = JSON.stringify({ response: response, cmd: 'remote console.log', type: msgType });

    if (remoteWindow) {
      remoteWindow.postMessage(msg, origin);
    } else {
      queue.push(msg);
    }

    msgType = '';
  },
  info: function () {
    msgType = 'info';
    remote.log.apply(this, arguments);
  },
  echo: function () {
    var args = [].slice.call(arguments, 0),
        plain = args.pop(),
        cmd = args.pop(),
        response = args;

    var argsObj = stringify(response, plain),
        msg = JSON.stringify({ response: argsObj, cmd: cmd });
    if (remoteWindow) {
      remoteWindow.postMessage(msg, origin);
    } else {
      queue.push(msg);
    }
  },
  error: function (error, cmd) {
    var msg = JSON.stringify({ response: error.message, cmd: cmd, type: 'error' });
    if (remoteWindow) {
      remoteWindow.postMessage(msg, origin);
    } else {
      queue.push(msg);
    }
  },
  time: function(title){
    if(typeof title !== 'string') {
      return;
    }
    timers[title] = +new Date();
  },
  timeEnd: function(title){
    if (typeof title !== 'string' || !timers[title]) {
      return;
    }
    var execTime = +new Date() - timers[title];
    delete timers[title];
    var plain = title + ': ' + execTime + 'ms';
    var msg = JSON.stringify({ response: plain, cmd:  'remote console.log', type: '' });
    if (remoteWindow) {
      remoteWindow.postMessage(msg, origin);
    } else {
      queue.push(msg);
    }
  }
};

// just for extra support
remote.debug = remote.dir = remote.log;
remote.warn = remote.info;

remoteFrame.onload = function () {
  remoteWindow = remoteFrame.contentWindow;
  remoteWindow.postMessage('__init__', origin);

  remoteWindow.postMessage(stringify({ response: 'Connection established with ' + window.location.toString() + '\n' + navigator.userAgent, type: 'info' }), origin);

  for (var i = 0; i < queue.length; i++) {
    remoteWindow.postMessage(queue[i], origin);
  }
};

window.remote = remote;

if (window.addEventListener) {
  window.addEventListener('error', function (event) {
    remote.error({ message: event.message }, event.filename + ':' + event.lineno);
  }, false);
}

try {
  window._console = window.console;
  window.console = remote;
} catch (e) {
  console.log('cannot overwrite existing console object');
}

function warnUsage() {
  var useSS = false;
  try {
    sessionStorage.getItem('foo');
    useSS = true;
  } catch (e) {}
  if (!(useSS ? sessionStorage.jsconsole : window.name)) {
    if (useSS) {
      sessionStorage.jsconsole = 1;
    } else {
      window.name = 1;
    }
    alert('You will see this warning once per session.\n\nYou are using a remote control script on this site - if you accidently push it to production, anyone will have control of your visitor\'s browser. Remember to remove this script.');
  }
}

warnUsage();

})();
<commit_msg>feat: support console.warn (#81)<commit_after>;(function () {
/* jshint browser:true, evil:true */

// 1. create iframe pointing to script on jsconsole.com domain
// 2. create console object with: log, dir, etc?
// 3. console.log runs postMessage with json.stringified content
// 4. jsconsole.com/remote/?id.onMessage = send to server, and wait for response.

function sortci(a, b) {
  return a.toLowerCase() < b.toLowerCase() ? -1 : 1;
}

// from console.js
function stringify(o, simple) {
  var json = '', i, type = ({}).toString.call(o), parts = [], names = [];

  if (type === '[object String]') {
    json = '"' + o.replace(/\n/g, '\\n').replace(/"/g, '\\"') + '"';
  } else if (type === '[object Array]') {
    json = '[';
    for (i = 0; i < o.length; i++) {
      parts.push(stringify(o[i], simple));
    }
    json += parts.join(', ') + ']';
  } else if (type === '[object Object]') {
    json = '{';
    for (i in o) {
      names.push(i);
    }
    names.sort(sortci);
    for (i = 0; i < names.length; i++) {
      parts.push(stringify(names[i]) + ': ' + stringify(o[names[i] ], simple));
    }
    json += parts.join(', ') + '}';
  } else if (type === '[object Number]') {
    json = o+'';
  } else if (type === '[object Boolean]') {
    json = o ? 'true' : 'false';
  } else if (type === '[object Function]') {
    json = o.toString();
  } else if (o === null) {
    json = 'null';
  } else if (o === undefined) {
    json = 'undefined';
  } else if (simple === undefined) {
    json = type + '{\n';
    for (i in o) {
      names.push(i);
    }
    names.sort(sortci);
    for (i = 0; i < names.length; i++) {
      // safety from max stack
      parts.push(names[i] + ': ' + stringify(o[names[i]], true));
    }
    json += parts.join(',\n') + '\n}';
  } else {
    try {
      json = o+''; // should look like an object
    } catch (e) {}
  }
  return json;
}

function getRemoteScript() {
  var scripts = document.getElementsByTagName('script');
  var remoteScript = scripts[scripts.length-1];
  var re = /jsconsole\..*(:\d+)?\/js\/remote.js/;
  for (var i = 0; i < scripts.length; i++) {
    if (re.test(scripts[i].src)) {
      remoteScript = scripts[i];
      break;
    }
  }

  return remoteScript;
}

var last = getRemoteScript();

var lastSrc = last.getAttribute('src'),
    id = lastSrc.replace(/.*\?/, ''),
    protocol = /https?:\/\//.exec(lastSrc)[0],
    origin = protocol + lastSrc.substr(protocol.length).replace(/\/.*$/, ''),
    remoteWindow = null,
    queue = [],
    msgType = '';

var remoteFrame = document.createElement('iframe');
remoteFrame.style.display = 'none';
remoteFrame.src = origin + '/remote.html?' + id;

// an attempt to allow this code to be included in the head element
document.documentElement.appendChild(remoteFrame);

window.addEventListener('message', function (event) {
  if (event.origin !== origin) {
    return;
  }

  // this isn't for us
  if (typeof event.data !== 'string') {
    return;
  }

  // eval the event.data command
  try {
    if (event.data.indexOf('console.log') === 0) {
      eval('remote.echo(' + event.data.match(/console.log\((.*)\);?/)[1] + ', "' + event.data + '", true)');
    } else {
      // must be undefined to work
      remote.echo(eval(event.data), event.data, undefined);
    }
  } catch (e) {
    _console.log(e.stack, event);
    remote.error(e, event.data);
  }
}, false);

var timers = {}; // timers for console.time and console.timeEnd

var remote = {
  log: function () {
    // var argsObj = stringify(arguments.length === 1 ? arguments[0] : [].slice.call(arguments, 0));
    var response = [];
    [].forEach.call(arguments, function (args) {
      response.push(stringify(args, true));
    });

    var msg = JSON.stringify({ response: response, cmd: 'remote console.log', type: msgType });

    if (remoteWindow) {
      remoteWindow.postMessage(msg, origin);
    } else {
      queue.push(msg);
    }

    msgType = '';
  },
  info: function () {
    msgType = 'info';
    remote.log.apply(this, arguments);
  },
  echo: function () {
    var args = [].slice.call(arguments, 0),
        plain = args.pop(),
        cmd = args.pop(),
        response = args;

    var argsObj = stringify(response, plain),
        msg = JSON.stringify({ response: argsObj, cmd: cmd });
    if (remoteWindow) {
      remoteWindow.postMessage(msg, origin);
    } else {
      queue.push(msg);
    }
  },
  error: function (error, cmd) {
    var msg = JSON.stringify({ response: error.message, cmd: cmd, type: 'error' });
    if (remoteWindow) {
      remoteWindow.postMessage(msg, origin);
    } else {
      queue.push(msg);
    }
  },
  time: function(title){
    if(typeof title !== 'string') {
      return;
    }
    timers[title] = +new Date();
  },
  timeEnd: function(title){
    if (typeof title !== 'string' || !timers[title]) {
      return;
    }
    var execTime = +new Date() - timers[title];
    delete timers[title];
    var plain = title + ': ' + execTime + 'ms';
    var msg = JSON.stringify({ response: plain, cmd:  'remote console.log', type: '' });
    if (remoteWindow) {
      remoteWindow.postMessage(msg, origin);
    } else {
      queue.push(msg);
    }
  },
  assert: function(condition, object){
    if(!condition) {
      remote.log(arguments.length);
      var message = 'Assertion failed';
      if (object) {
        message += ': ' + stringify(object);
      }
      remote.log(message)
      remote.error({ message: message });
    }
  }
};

// just for extra support
remote.debug = remote.dir = remote.log;
remote.warn = remote.info;

remoteFrame.onload = function () {
  remoteWindow = remoteFrame.contentWindow;
  remoteWindow.postMessage('__init__', origin);

  remoteWindow.postMessage(stringify({ response: 'Connection established with ' + window.location.toString() + '\n' + navigator.userAgent, type: 'info' }), origin);

  for (var i = 0; i < queue.length; i++) {
    remoteWindow.postMessage(queue[i], origin);
  }
};

window.remote = remote;

if (window.addEventListener) {
  window.addEventListener('error', function (event) {
    remote.error({ message: event.message }, event.filename + ':' + event.lineno);
  }, false);
}

try {
  window._console = window.console;
  window.console = remote;
} catch (e) {
  console.log('cannot overwrite existing console object');
}

function warnUsage() {
  var useSS = false;
  try {
    sessionStorage.getItem('foo');
    useSS = true;
  } catch (e) {}
  if (!(useSS ? sessionStorage.jsconsole : window.name)) {
    if (useSS) {
      sessionStorage.jsconsole = 1;
    } else {
      window.name = 1;
    }
    alert('You will see this warning once per session.\n\nYou are using a remote control script on this site - if you accidently push it to production, anyone will have control of your visitor\'s browser. Remember to remove this script.');
  }
}

warnUsage();

})();
<|endoftext|>


<commit_before>/*
 * @constructor
 * @this {Render}
 * @param {string} canvasId
 * @param {Room} room
 */
var Render = function(canvasId, room) {
	this.canvas = $(canvasId)[0];
	this.context = this.canvas.getContext("2d");
	var self = this;
	$(this.canvas).on("click", function(e) {
		self.onClick(e);
	}, false);

	this.room = room;

	this.hexShape = {
		radius : 36,
		apothem : 31,
		smallRadius : 36,
		smallApothem : 31
		//smallRadius : 33,
		//smallApothem : 28.6
	}

	this.xOffset = this.hexShape.radius + 1;
	this.yOffset = 2 * this.hexShape.apothem + 1;

	this.clickedSpace = {
		i : -1,
		j : -1
	};

	this.possibleMoves = {};
	this.colors = [{
		color : "#caa",
		activeColor : "#d66",
		moveColor : "#edd"
	}, {
		color : "#aca",
		activeColor : "#6d6",
		moveColor : "#ded"
	}, {
		color : "#aac",
		activeColor : "#66d",
		moveColor : "#dde"
	}];

	this.centerSpace = this.hexSpaceCenter(4, 3);
}

/*
 * @param {i} i
 * @param {j} j
 * @return {Coordiante} {x,y}
 */
Render.prototype.hexSpaceCenter = function(i, j) {

	var x = i * (1.5 * this.hexShape.radius);
	var y = j * (2 * this.hexShape.apothem);
	if (i % 2 == 1) {
		y -= this.hexShape.apothem;
	}

	// Middle spaces have slightly different centers
	if (i == 4 && j == 2) {
		y = this.centerSpace.y - 2 * this.hexShape.smallApothem - this.yOffset;
	} else if (i == 3 && j == 3) {
		x = this.centerSpace.x - 1.5 * this.hexShape.smallRadius - this.xOffset;
		y = this.centerSpace.y - this.hexShape.smallApothem - this.yOffset;
	} else if (i == 5 && j == 3) {
		x = this.centerSpace.x + 1.5 * this.hexShape.smallRadius - this.xOffset;
		y = this.centerSpace.y - this.hexShape.smallApothem - this.yOffset;
	} else if (i == 3 && j == 4) {
		x = this.centerSpace.x - 1.5 * this.hexShape.smallRadius - this.xOffset;
		y = this.centerSpace.y + this.hexShape.smallApothem - this.yOffset;
	} else if (i == 4 && j == 4) {
		y = this.centerSpace.y + 2 * this.hexShape.smallApothem - this.yOffset;
	} else if (i == 5 && j == 4) {
		x = this.centerSpace.x + 1.5 * this.hexShape.smallRadius - this.xOffset;
		y = this.centerSpace.y + this.hexShape.smallApothem - this.yOffset;
	}

	return {
		x : x + this.xOffset,
		y : y + this.yOffset
	};
}

/*
 * @param {Event} e
 * @return {Coordinate} {x,y}
 */
Render.prototype.getCursorPosition = function(e) {
	var x, y;
	if (e.pageX != undefined && e.pageY != undefined) {
		x = e.pageX;
		y = e.pageY;
	} else {
		x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
		y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
	}

	x -= this.canvas.offsetLeft;
	y -= this.canvas.offsetTop;

	return {
		x : x,
		y : y
	};
}

/*
 * @param {Coordinate.X} canvas_x
 * @param {Coordinate.Y} canvas_y
 * @return {Position}
 */
Render.prototype.spaceAt = function(canvas_x, canvas_y) {
	var high_i = Math.floor(canvas_x / (1.5 * this.hexShape.radius));
	var high_j = Math.floor(canvas_y / (2 * this.hexShape.apothem));

	var min_i = -1, min_j = -1, min_d = 1600;
	var space, d;

	for (var i = high_i - 1; i < high_i + 1; i++) {
		for (var j = high_j - 1; j < high_j + 1; j++) {

			space = this.hexSpaceCenter(i, j);
			d = distance2(canvas_x, canvas_y, space.x, space.y);

			if (d < min_d) {
				min_i = i;
				min_j = j;
				min_d = d;
			}
		}
	}

	return {
		i : min_i,
		j : min_j
	};
}

Render.prototype.getDimensions = function() {
    var width = (2 * this.hexShape.radius) * this.room.game.rules.board.width + 2;
    if (this.room.game.rules.board.width % 2 === 0) {
        width += .5 * this.hexShape.radius;
    }
    var height = (2 * this.hexShape.apothem) * this.room.game.rules.board.height + 2;
    if (this.room.game.rules.board.height % 2 === 0) {
        height += this.hexShape.apothem;
    }
    return {width : width, height : height};
}

/*
 * @param {Event} e
 */
Render.prototype.onClick = function(e) {
	console.log("clicked")
	var clicked = this.getCursorPosition(e);
	var space = this.spaceAt(clicked.x, clicked.y);
	try {
		if (this.room.game.grid[space.i][space.j] == -2) {
			console.log("1")
			return;
		}
	} catch(e) {
		console.log("2")
		return;
	}

	if (this.room.currentPlayerId() !== this.room.me) {
		console.log("not your turn")
		return;
	}

	console.log(this.room.game.grid[space.i][space.j])
	if (this.room.game.grid[space.i][space.j] === this.room.me && this.clickedSpace.i === -1 && this.clickedSpace.j === -1) {
		this.clickedSpace.i = space.i;
		this.clickedSpace.j = space.j;

		this.possibleMoves = this.room.game.generateMoves(space);
	} else if (this.clickedSpace.i == space.i && this.clickedSpace.j == space.j) {
		this.clickedSpace.i = -1;
		this.clickedSpace.j = -1;
		this.possibleMoves = {};
	} else {
		// Validate locally
		if (!this.possibleMoves[[space.i, space.j]]) {
			return;
		}

		// Send move to server
		this.room.move({start: this.clickedSpace, end: space});
		this.room.connect.move({
			start : this.clickedSpace,
			end : space
		});

		this.possibleMoves = {};
		this.clickedSpace = {
			i : -1,
			j : -1
		}
	}

	this.draw();
}

//TODO: move this to room
Render.prototype.index = function(id) {
	for (var i = 0; i < this.room.players.length; i++) {
		if (this.room.players[i].id === id) {
			return i
		}
	}
	return -1;
}

// Draw
Render.prototype.draw = function() {

    if (!this.room.game) {
    	console.log("no game")
        return;
    }

	// clear canvas
    var dim = this.getDimensions();
    this.canvas.width = dim.width;
    this.canvas.height = dim.height;

    for (var i = 0; i < this.room.game.rules.board.width; i++) {
		for (var j = 0; j < this.room.game.rules.board.height; j++) {

			var space = this.hexSpaceCenter(i, j);
			var fill = "#fff";

			// Weed out non-spaces
			if (this.room.game.grid[i][j] == -2) {
				continue;
			}

			// Fill
            if (this.room.game.grid[i][j] === -3) {
				fill = "#444";
            } else if (this.room.game.grid[i][j] <= -4) {

            } else if (this.room.game.grid[i][j] !== -1) {
				var index = this.index(this.room.game.grid[i][j])
				var colors = this.colors[index];
				if (!colors) {
					colors = {
						color : "#333",
						activeColor : "#333",
						moveColor : "#333"
					}
				}
				if (i === this.clickedSpace.i && j === this.clickedSpace.j) {
					fill = colors.activeColor;
				} else {
					fill = colors.color;
				}
			} else if (this.possibleMoves[[i, j]]) {
				var index = this.index(this.room.me);
				var colors = this.colors[index];
				if (!colors) {
					colors = {
						color : "#333",
						activeColor : "#333",
						moveColor : "#333"
					}
				}
				fill = colors.moveColor;
			}

			// Draw Hex Spaces
            this.drawHexSpace(space.x, space.y, this.hexShape.radius, fill);

            var s = {i: i, j: j};
            if (this.room.game.rules.board.gametype === "pointcontrol" && this.room.game.rules.isControlPoint(s)) {
                this.context.beginPath();
                this.context.arc(space.x, space.y, 18, 0, 2 * Math.PI, false);
                this.context.fillStyle = "#FFB00F";
                this.context.fill();
            }

            if (DEBUG) {
                this.context.fillStyle = "#000";
                this.context.font = "12px sans-serif";
                this.context.fillText(i + " " + j, space.x - 7, space.y + 4);
            }
        }
    }
}

Render.prototype.drawHexSpace = function(x, y, radius, fill) {

	this.context.beginPath();
	this.context.translate(x, y);

	for (var i = 0; i < 6; i++) {
		this.context.rotate((2 * Math.PI) / 6);
		this.context.lineTo(radius, 0);
	}

	this.context.closePath();
	if (fill) {
		this.context.fillStyle = fill;
		this.context.fill();
	}
	this.context.stroke();

	this.context.setTransform(1, 0, 0, 1, 0, 0);
}

<commit_msg>better control<commit_after>/*
 * @constructor
 * @this {Render}
 * @param {string} canvasId
 * @param {Room} room
 */
var Render = function(canvasId, room) {
	this.canvas = $(canvasId)[0];
	this.context = this.canvas.getContext("2d");
	var self = this;
	$(this.canvas).on("click", function(e) {
		self.onClick(e);
	}, false);

	this.room = room;

	this.hexShape = {
		radius : 36,
		apothem : 31,
		smallRadius : 36,
		smallApothem : 31
		//smallRadius : 33,
		//smallApothem : 28.6
	}

	this.xOffset = this.hexShape.radius + 1;
	this.yOffset = 2 * this.hexShape.apothem + 1;

	this.clickedSpace = {
		i : -1,
		j : -1
	};

	this.possibleMoves = {};
	this.colors = [{
		color : "#caa",
		activeColor : "#d66",
		moveColor : "#edd"
	}, {
		color : "#aca",
		activeColor : "#6d6",
		moveColor : "#ded"
	}, {
		color : "#aac",
		activeColor : "#66d",
		moveColor : "#dde"
	}];

	this.centerSpace = this.hexSpaceCenter(4, 3);
}

/*
 * @param {i} i
 * @param {j} j
 * @return {Coordiante} {x,y}
 */
Render.prototype.hexSpaceCenter = function(i, j) {

	var x = i * (1.5 * this.hexShape.radius);
	var y = j * (2 * this.hexShape.apothem);
	if (i % 2 == 1) {
		y -= this.hexShape.apothem;
	}

	// Middle spaces have slightly different centers
	if (i == 4 && j == 2) {
		y = this.centerSpace.y - 2 * this.hexShape.smallApothem - this.yOffset;
	} else if (i == 3 && j == 3) {
		x = this.centerSpace.x - 1.5 * this.hexShape.smallRadius - this.xOffset;
		y = this.centerSpace.y - this.hexShape.smallApothem - this.yOffset;
	} else if (i == 5 && j == 3) {
		x = this.centerSpace.x + 1.5 * this.hexShape.smallRadius - this.xOffset;
		y = this.centerSpace.y - this.hexShape.smallApothem - this.yOffset;
	} else if (i == 3 && j == 4) {
		x = this.centerSpace.x - 1.5 * this.hexShape.smallRadius - this.xOffset;
		y = this.centerSpace.y + this.hexShape.smallApothem - this.yOffset;
	} else if (i == 4 && j == 4) {
		y = this.centerSpace.y + 2 * this.hexShape.smallApothem - this.yOffset;
	} else if (i == 5 && j == 4) {
		x = this.centerSpace.x + 1.5 * this.hexShape.smallRadius - this.xOffset;
		y = this.centerSpace.y + this.hexShape.smallApothem - this.yOffset;
	}

	return {
		x : x + this.xOffset,
		y : y + this.yOffset
	};
}

/*
 * @param {Event} e
 * @return {Coordinate} {x,y}
 */
Render.prototype.getCursorPosition = function(e) {
	var x, y;
	if (e.pageX != undefined && e.pageY != undefined) {
		x = e.pageX;
		y = e.pageY;
	} else {
		x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
		y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
	}

	x -= this.canvas.offsetLeft;
	y -= this.canvas.offsetTop;

	return {
		x : x,
		y : y
	};
}

/*
 * @param {Coordinate.X} canvas_x
 * @param {Coordinate.Y} canvas_y
 * @return {Position}
 */
Render.prototype.spaceAt = function(canvas_x, canvas_y) {
	var high_i = Math.floor(canvas_x / (1.5 * this.hexShape.radius));
	var high_j = Math.floor(canvas_y / (2 * this.hexShape.apothem));

	var min_i = -1, min_j = -1, min_d = 1600;
	var space, d;

	for (var i = high_i - 1; i < high_i + 1; i++) {
		for (var j = high_j - 1; j < high_j + 1; j++) {

			space = this.hexSpaceCenter(i, j);
			d = distance2(canvas_x, canvas_y, space.x, space.y);

			if (d < min_d) {
				min_i = i;
				min_j = j;
				min_d = d;
			}
		}
	}

	return {
		i : min_i,
		j : min_j
	};
}

Render.prototype.getDimensions = function() {
    var width = (2 * this.hexShape.radius) * this.room.game.rules.board.width + 2;
    if (this.room.game.rules.board.width % 2 === 0) {
        width += .5 * this.hexShape.radius;
    }
    var height = (2 * this.hexShape.apothem) * this.room.game.rules.board.height + 2;
    if (this.room.game.rules.board.height % 2 === 0) {
        height += this.hexShape.apothem;
    }
    return {width : width, height : height};
}

/*
 * @param {Event} e
 */
Render.prototype.onClick = function(e) {
	console.log("clicked")
	var clicked = this.getCursorPosition(e);
	var space = this.spaceAt(clicked.x, clicked.y);
	try {
		if (this.room.game.grid[space.i][space.j] == -2) {
			console.log("1")
			return;
		}
	} catch(e) {
		console.log("2")
		return;
	}

	if (this.room.currentPlayerId() !== this.room.me) {
		console.log("not your turn")
		return;
	}

	console.log(this.room.game.grid[space.i][space.j])
	if (this.room.game.grid[space.i][space.j] === this.room.me) {
		this.clickedSpace.i = space.i;
		this.clickedSpace.j = space.j;

		this.possibleMoves = this.room.game.generateMoves(space);
	} else if (this.clickedSpace.i == space.i && this.clickedSpace.j == space.j) {
		this.clickedSpace.i = -1;
		this.clickedSpace.j = -1;
		this.possibleMoves = {};
	} else {
		// Validate locally
		if (!this.possibleMoves[[space.i, space.j]]) {
			return;
		}

		// Send move to server
		this.room.move({start: this.clickedSpace, end: space});
		this.room.connect.move({
			start : this.clickedSpace,
			end : space
		});

		this.possibleMoves = {};
		this.clickedSpace = {
			i : -1,
			j : -1
		}
	}

	this.draw();
}

//TODO: move this to room
Render.prototype.index = function(id) {
	for (var i = 0; i < this.room.players.length; i++) {
		if (this.room.players[i].id === id) {
			return i
		}
	}
	return -1;
}

// Draw
Render.prototype.draw = function() {

    if (!this.room.game) {
    	console.log("no game")
        return;
    }

	// clear canvas
    var dim = this.getDimensions();
    this.canvas.width = dim.width;
    this.canvas.height = dim.height;

    for (var i = 0; i < this.room.game.rules.board.width; i++) {
		for (var j = 0; j < this.room.game.rules.board.height; j++) {

			var space = this.hexSpaceCenter(i, j);
			var fill = "#fff";

			// Weed out non-spaces
			if (this.room.game.grid[i][j] == -2) {
				continue;
			}

			// Fill
            if (this.room.game.grid[i][j] === -3) {
				fill = "#444";
            } else if (this.room.game.grid[i][j] <= -4) {

            } else if (this.room.game.grid[i][j] !== -1) {
				var index = this.index(this.room.game.grid[i][j])
				var colors = this.colors[index];
				if (!colors) {
					colors = {
						color : "#333",
						activeColor : "#333",
						moveColor : "#333"
					}
				}
				if (i === this.clickedSpace.i && j === this.clickedSpace.j) {
					fill = colors.activeColor;
				} else {
					fill = colors.color;
				}
			} else if (this.possibleMoves[[i, j]]) {
				var index = this.index(this.room.me);
				var colors = this.colors[index];
				if (!colors) {
					colors = {
						color : "#333",
						activeColor : "#333",
						moveColor : "#333"
					}
				}
				fill = colors.moveColor;
			}

			// Draw Hex Spaces
            this.drawHexSpace(space.x, space.y, this.hexShape.radius, fill);

            var s = {i: i, j: j};
            if (this.room.game.rules.board.gametype === "pointcontrol" && this.room.game.rules.isControlPoint(s)) {
                this.context.beginPath();
                this.context.arc(space.x, space.y, 18, 0, 2 * Math.PI, false);
                this.context.fillStyle = "#FFB00F";
                this.context.fill();
            }

            if (DEBUG) {
                this.context.fillStyle = "#000";
                this.context.font = "12px sans-serif";
                this.context.fillText(i + " " + j, space.x - 7, space.y + 4);
            }
        }
    }
}

Render.prototype.drawHexSpace = function(x, y, radius, fill) {

	this.context.beginPath();
	this.context.translate(x, y);

	for (var i = 0; i < 6; i++) {
		this.context.rotate((2 * Math.PI) / 6);
		this.context.lineTo(radius, 0);
	}

	this.context.closePath();
	if (fill) {
		this.context.fillStyle = fill;
		this.context.fill();
	}
	this.context.stroke();

	this.context.setTransform(1, 0, 0, 1, 0, 0);
}

<|endoftext|>