<commit_before>if (!CMS.Models['Settings']) CMS.Models.Settings = new Object();

CMS.Models.Settings.CourseDetails = Backbone.Model.extend({
	defaults: {
		location : null,	// the course's Location model, required
		start_date: null,	// maps to 'start'
		end_date: null,		// maps to 'end'
		enrollment_start: null,
		enrollment_end: null,
		syllabus: null,
		overview: "",
		intro_video: null,
		effort: null	// an int or null
	},
	
	// When init'g from html script, ensure you pass {parse: true} as an option (2nd arg to reset)
	parse: function(attributes) {
		if (attributes['course_location']) {
			attributes.location = new CMS.Models.Location(attributes.course_location, {parse:true});
		}
		if (attributes['start_date']) {
			attributes.start_date = new Date(attributes.start_date);
		}
		if (attributes['end_date']) {
			attributes.end_date = new Date(attributes.end_date);
		}
		if (attributes['enrollment_start']) {
			attributes.enrollment_start = new Date(attributes.enrollment_start);
		}
		if (attributes['enrollment_end']) {
			attributes.enrollment_end = new Date(attributes.enrollment_end);
		}
		return attributes;
	},
	
	validate: function(newattrs) {
		// Returns either nothing (no return call) so that validate works or an object of {field: errorstring} pairs
		// A bit funny in that the video key validation is asynchronous; so, it won't stop the validation.
		var errors = {};
		if (newattrs.start_date && newattrs.end_date && newattrs.start_date >= newattrs.end_date) {
			errors.end_date = "The course end date cannot be before the course start date.";
		}
		if (newattrs.start_date && newattrs.enrollment_start && newattrs.start_date < newattrs.enrollment_start) {
			errors.enrollment_start = "The course start date cannot be before the enrollment start date.";
		}
		if (newattrs.enrollment_start && newattrs.enrollment_end && newattrs.enrollment_start >= newattrs.enrollment_end) {
			errors.enrollment_end = "The enrollment start date cannot be after the enrollment end date.";
		}
		if (newattrs.end_date && newattrs.enrollment_end && newattrs.end_date < newattrs.enrollment_end) {
			errors.enrollment_end = "The enrollment end date cannot be after the course end date.";
		}
		if (newattrs.intro_video && newattrs.intro_video != this.get('intro_video')) {
			var videos = this.parse_videosource(newattrs.intro_video);
			var vid_errors = new Array();
			var cachethis = this;
			for (var i=0; i<videos.length; i++) {
				// doesn't call parseFloat or Number b/c they stop on first non parsable and return what they have
				if (!isFinite(videos[i].speed)) vid_errors.push(videos[i].speed + " is not a valid speed.");
				else if (!videos[i].key) vid_errors.push(videos[i].speed + " does not have a video id");
				// can't use get from client to test if video exists b/c of CORS (crossbrowser get not allowed)
				// GET "http://gdata.youtube.com/feeds/api/videos/" + videokey
			}
			if (!_.isEmpty(vid_errors)) {
				errors.intro_video = vid_errors.join('/n');
			}
		}
		if (!_.isEmpty(errors)) return errors;
		// NOTE don't return empty errors as that will be interpreted as an error state
	},
	
	url: function() {
		var location = this.get('location');<commit_msg>Fixed infinite loop in the 2nd video string parser which I'd fixed in the first yesterday. Fixed formatting of compounded video string errors.<commit_after>if (!CMS.Models['Settings']) CMS.Models.Settings = new Object();

CMS.Models.Settings.CourseDetails = Backbone.Model.extend({
	defaults: {
		location : null,	// the course's Location model, required
		start_date: null,	// maps to 'start'
		end_date: null,		// maps to 'end'
		enrollment_start: null,
		enrollment_end: null,
		syllabus: null,
		overview: "",
		intro_video: null,
		effort: null	// an int or null
	},
	
	// When init'g from html script, ensure you pass {parse: true} as an option (2nd arg to reset)
	parse: function(attributes) {
		if (attributes['course_location']) {
			attributes.location = new CMS.Models.Location(attributes.course_location, {parse:true});
		}
		if (attributes['start_date']) {
			attributes.start_date = new Date(attributes.start_date);
		}
		if (attributes['end_date']) {
			attributes.end_date = new Date(attributes.end_date);
		}
		if (attributes['enrollment_start']) {
			attributes.enrollment_start = new Date(attributes.enrollment_start);
		}
		if (attributes['enrollment_end']) {
			attributes.enrollment_end = new Date(attributes.enrollment_end);
		}
		return attributes;
	},
	
	validate: function(newattrs) {
		// Returns either nothing (no return call) so that validate works or an object of {field: errorstring} pairs
		// A bit funny in that the video key validation is asynchronous; so, it won't stop the validation.
		var errors = {};
		if (newattrs.start_date && newattrs.end_date && newattrs.start_date >= newattrs.end_date) {
			errors.end_date = "The course end date cannot be before the course start date.";
		}
		if (newattrs.start_date && newattrs.enrollment_start && newattrs.start_date < newattrs.enrollment_start) {
			errors.enrollment_start = "The course start date cannot be before the enrollment start date.";
		}
		if (newattrs.enrollment_start && newattrs.enrollment_end && newattrs.enrollment_start >= newattrs.enrollment_end) {
			errors.enrollment_end = "The enrollment start date cannot be after the enrollment end date.";
		}
		if (newattrs.end_date && newattrs.enrollment_end && newattrs.end_date < newattrs.enrollment_end) {
			errors.enrollment_end = "The enrollment end date cannot be after the course end date.";
		}
		if (newattrs.intro_video && newattrs.intro_video != this.get('intro_video')) {
			var videos = this.parse_videosource(newattrs.intro_video);
			var vid_errors = new Array();
			var cachethis = this;
			for (var i=0; i<videos.length; i++) {
				// doesn't call parseFloat or Number b/c they stop on first non parsable and return what they have
				if (!isFinite(videos[i].speed)) vid_errors.push(videos[i].speed + " is not a valid speed.");
				else if (!videos[i].key) vid_errors.push(videos[i].speed + " does not have a video id");
				// can't use get from client to test if video exists b/c of CORS (crossbrowser get not allowed)
				// GET "http://gdata.youtube.com/feeds/api/videos/" + videokey
			}
			if (!_.isEmpty(vid_errors)) {
				errors.intro_video = vid_errors.join(' ');
			}
		}
		if (!_.isEmpty(errors)) return errors;
		// NOTE don't return empty errors as that will be interpreted as an error state
	},
	
	url: function() {
		var location = this.get('location');
{'fraction_non_alphanumeric': 0.11964504283965728, 'fraction_numerical': 0.0007649938800489596, 'mean_word_length': 4.08715953307393, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4145151', 'n_tokens_mistral': 2247, 'n_tokens_neox': 2034, 'n_words': 617}