<commit_before># a track is an observable / drawable model of a woooden train track comprising
# multiple pieces of different types connected together
class Track
	constructor: (@start=new Transform(0,0,0), options={}) ->
		@gridSize = options.gridSize ? 100
		@trackWidth = options.trackWidth ? 16
		@trackGap = options.trackGap ? 1
		@_sections = []
		@_listeners = {}
		@_gapTransform = new Transform(@trackGap, 0, 0)

	# Next three methods make class observable.  For template see
	# http://www.nczonline.net/blog/2010/03/09/custom-events-in-javascript/

	# attach listener to "add", "remove", "change" or "clear" types of event
	on: (types, listener) ->
		types.split(" ").forEach (type) =>
			if !@_listeners[type]? then @_listeners[type] = []
			@_listeners[type].push(listener)

	# remove listener from particular types of event
	off: (types, listener) ->
		types.split(" ").forEach (type) =>
			@_listeners[type].splice(idx, 1) for l, idx in @_listeners[type] when l==listener

	_fire: (event) ->
		if typeof event == "string" then event = { type: event }
		if !event.target then event.target = @
		if !event.type then throw new Error "Event missing 'type' property."
		if @_listeners[event.type] instanceof Array
			@_listeners[event.type].forEach (listener) -> listener.call(this, event)

	# update property and fire "change" event
	# todo: use 'dirty' state to recalculate connection transforms when gridSize or trackGap are changed
	set: (property, value) ->
		if value!=@[property]
			@[property]=value
			@_fire { type: 'change', target: @ }

	# available connection codes<commit_msg>track.set('trackGap', 3) now updates the whole track correctly instantly.  A few lingering issues though, especially with remove.<commit_after># a track is an observable / drawable model of a woooden train track comprising
# multiple pieces of different types connected together
class Track
	constructor: (@start=new Transform(0,0,0), options={}) ->
		@gridSize = options.gridSize ? 100
		@trackWidth = options.trackWidth ? 16
		@trackGap = options.trackGap ? 1
		@_sections = []
		@_listeners = {}
		@_gapTransform = new Transform(@trackGap, 0, 0)

	# Next three methods make class observable.  For template see
	# http://www.nczonline.net/blog/2010/03/09/custom-events-in-javascript/

	# attach listener to "add", "remove", "change" or "clear" types of event
	on: (types, listener) ->
		types.split(" ").forEach (type) =>
			if !@_listeners[type]? then @_listeners[type] = []
			@_listeners[type].push(listener)

	# remove listener from particular types of event
	off: (types, listener) ->
		types.split(" ").forEach (type) =>
			@_listeners[type].splice(idx, 1) for l, idx in @_listeners[type] when l==listener

	_fire: (event) ->
		if typeof event == "string" then event = { type: event }
		if !event.target then event.target = @
		if !event.type then throw new Error "Event missing 'type' property."
		if @_listeners[event.type] instanceof Array
			@_listeners[event.type].forEach (listener) -> listener.call(this, event)

	# update property and fire "change" event
	set: (property, value) ->
		if value!=@[property]
			@[property]=value
			switch property
				when 'trackGap'
					@_gapTransform = new Transform(value, 0, 0)
			@_fire { type: 'change', target: @ }

	# available connection codes
{'fraction_non_alphanumeric': 0.13303030303030303, 'fraction_numerical': 0.013030303030303031, 'mean_word_length': 4.248012718600954, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '1513884', 'n_tokens_mistral': 1132, 'n_tokens_neox': 1021, 'n_words': 334}