UNPKG

codehs-graphics

Version:

Helpers used to run graphics problems in the CodeHS editor.

349 lines (323 loc) 10.7 kB
'use strict'; /** * @constructor */ function Thing() { this.x = 0; this.y = 0; this.color = '#000000'; this.stroke = '#000000'; this.type = 'Thing'; this.lineWidth = 1; this.filled = true; this.hasBorder = false; this.rotation = 0; } Thing.DEGREES = 0; Thing.RADIANS = 1; /** * Sets a Thing object to filled. * Throws an error if an argument is not passed. * * @param {bool} filled - A boolean of whether or not Thing is filled. */ Thing.prototype.setFilled = function(filled) { if (arguments.length !== 1) { throw new Error('You should pass exactly 1 argument to ' + '<span class="code">setFilled</span>'); } if (typeof filled !== 'boolean') { throw new Error('Invalid value passed to <span class="code">' + 'setFilled</span>. Make sure you are passing a ' + 'boolean value.'); } this.filled = filled; }; /** * Returns if a Thing is filled. * * @returns {boolean} True if the Thing is filled. */ Thing.prototype.isFilled = function() { return this.filled; }; /** * Sets a Thing object to filled. * Throws an error if an argument is not passed. * * @param {bool} hasBorder - A boolean of whether or not Thing has a border. */ Thing.prototype.setBorder = function(hasBorder) { if (arguments.length !== 1) { throw new Error('You should pass exactly 1 argument to <span class=' + '"code">setBorder</span>'); } if (typeof hasBorder !== 'boolean') { throw new Error('Invalid value passed to <span class="code">' + 'setBorder</span>. Make sure you are passing a ' + 'boolean value.'); } this.hasBorder = hasBorder; }; /** * Returns if a Thing has a border. * * @returns {boolean} True if the Thing has a border. */ Thing.prototype.hasBorder = function() { return this.hasBorder; }; /** * Sets a Thing object's type. * Questionable of whether or not this method is used. * * @param {type} type - A type to set the Thing to. */ Thing.prototype.setType = function(type) { if (arguments.length !== 1) { throw new Error('You should pass exactly 1 argument to <span ' + 'class="code">setType</span>'); } this.type = type; }; /** * Returns the type of a Thing. * * @returns {type} The type of the Thing. */ Thing.prototype.getType = function() { return this.type; }; /** * Sets the position of a Thing. * Throws an error if there are fewer than 2 params or if * they are not numbers. * * @param {number} x - The destination x coordinate of this Thing. * @param {number} y - The destination y coordinate of this Thing. */ Thing.prototype.setPosition = function(x, y) { if (arguments.length !== 2) { throw new Error('You should pass exactly 2 arguments to <span ' + 'class="code">setPosition(x, y)</span>'); } if (typeof x !== 'number' || !isFinite(x)) { throw new TypeError('Invalid value for x-coordinate. ' + 'Make sure you are passing finite numbers to <span ' + 'class="code">setPosition(x, y)</span>. Did you ' + 'forget the parentheses in <span class="code">getWidth()</span> ' + 'or <span class="code">getHeight()</span>? Or did you perform a ' + 'calculation on a variable that is not a number?'); } if (typeof y !== 'number' || !isFinite(y)) { throw new TypeError('Invalid value for y-coordinate. ' + 'Make sure you are passing finite numbers to <span ' + 'class="code">setPosition(x, y)</span>. Did you ' + 'forget the parentheses in <span class="code">getWidth()</span> ' + 'or <span class="code">getHeight()</span>? Or did you perform a ' + 'calculation on a variable that is not a number?'); } this.x = x; this.y = y; }; /** * Sets the rotation of a Thing in degrees. * Throws an error if there are fewer than 1 params or if they * are not numbers. * * @param {number} degrees - The degrees to rotate degrees. * @param {number} angleUnit - Whether it is degrees or radians. Defaults to * degrees. */ Thing.prototype.setRotation = function(degrees, angleUnit) { if (arguments.length < 1 || arguments.length > 2) { throw new Error('You should pass 1 or 2 arguments to <span ' + 'class="code">setRotation(degrees, angleUnit)</span>'); } if (typeof degrees !== 'number' || !isFinite(degrees)) { throw new TypeError('Invalid value for degrees. ' + 'Make sure you are passing finite numbers to <span ' + 'class="code">setRotation(degrees, angleUnit)</span>. Did you ' + 'perform a calculation on a variable that is not a number?'); } if (!angleUnit) { angleUnit = Thing.DEGREES; } if (typeof angleUnit !== 'number' || !isFinite(angleUnit)) { throw new TypeError('Invalid value for <span class="code">angleUnit' + '</span>. Make sure you are passing finite numbers to <span ' + 'class="code">setRotation(degrees, angleUnit)</span>'); } if (angleUnit == Thing.DEGREES) { this.rotation = degrees * Math.PI / 180; } else { this.rotation = degrees; } }; /** * Rotates a Thing an additional amount of degrees. * * @param {number} degrees - The degrees to rotate degrees. * @param {number} angleUnit - Whether it is degrees or radians. Defaults to * degrees. */ Thing.prototype.rotate = function(degrees, angleUnit) { if (arguments.length < 1 || arguments.length > 2) { throw new Error('You should pass exactly 1 argument to <span ' + 'class="code">rotate(degrees, angleUnit)</span>'); } if (typeof degrees !== 'number' || !isFinite(degrees)) { throw new TypeError('Invalid value for degrees. ' + 'Make sure you are passing finite numbers to <span ' + 'class="code">rotate(degrees, angleUnit)</span>. Did you perform ' + 'a calculation on a variable that is not a number?'); } if (!angleUnit) { angleUnit = Thing.DEGREES; } if (typeof angleUnit !== 'number' || !isFinite(angleUnit)) { throw new TypeError('Invalid value for <span class="code">angleUnit' + '</span>. Make sure you are passing finite numbers to <span ' + 'class="code">rotate(degrees, angleUnit)</span>'); } if (angleUnit == Thing.DEGREES) { this.rotation += degrees * Math.PI / 180; } else { this.rotation += degrees; } }; /** * Sets the color of a Thing. * Throws an error if there are fewer than 1 params or if * the param is undefined. * * @param {Color} color - The resulting color of Thing. */ Thing.prototype.setColor = function(color) { if (arguments.length !== 1) { throw new Error('You should pass exactly 1 argument to <span ' + 'class="code">setColor</span>'); } if (color === undefined) { throw new TypeError('Invalid color'); } this.color = color; }; /** * Gets the color of a Thing. * * @returns {Color} The destination y coordinate of this Thing. */ Thing.prototype.getColor = function() { return this.color; }; /** * Sets the border color of a Thing. * Throws an error if there are fewer than 1 params or if * the param is undefined. * * @param {Color} color - The resulting color of the Thing's border. */ Thing.prototype.setBorderColor = function(color) { if (arguments.length !== 1) { throw new Error('You should pass exactly 1 argument to <span ' + 'class="code">setBorderColor</span>'); } if (color === undefined) { throw new TypeError('Invalid color.'); } this.stroke = color; this.hasBorder = true; }; /** * Gets the border color of a Thing. * * @returns {Color} The color of the Thing's border. */ Thing.prototype.getBorderColor = function() { return this.stroke; }; /** * Sets the width of a Thing's border. * Throws an error if there is not 1 argument. * * @param {number} width - The resulting width of the Thing's border. */ Thing.prototype.setBorderWidth = function(width) { if (arguments.length !== 1) { throw new Error('You should pass exactly 1 argument to <span ' + 'class="code">setBorderWidth</span>'); } if (typeof width !== 'number' || !isFinite(width)) { throw new Error('Invalid value for border width. Make sure you are ' + 'passing a finite number to <span class="code">' + 'setBorderWidth</span>'); } this.lineWidth = width; this.hasBorder = true; }; /** * Gets the width of the Thing's border. * * @returns {number} The width of the Thing's border. */ Thing.prototype.getBorderWidth = function() { return this.lineWidth; }; /** * Changes the possition of a thing by a specified x and y amount. * * @param {number} dx - The resulting change in the Thing's x position. * @param {number} dy - The resulting change in the Thing's y position. */ Thing.prototype.move = function(dx, dy) { if (arguments.length !== 2) { throw new Error('You should pass exactly 2 arguments to <span ' + 'class="code">move</span>'); } if (typeof dx !== 'number' || !isFinite(dx)) { throw new TypeError('Invalid number passed for <span class="code">' + 'dx</span>. Make sure you are passing finite numbers to <span ' + 'class="code">move(dx, dy)</span>'); } if (typeof dy !== 'number' || !isFinite(dy)) { throw new TypeError('Invalid number passed for <span class="code">' + 'dy</span>. Make sure you are passing finite numbers to <span ' + 'class="code">move(dx, dy)</span>'); } this.x += dx; this.y += dy; }; /** * Gets the x position of the Thing. * * @returns {number} The x position of the Thing. */ Thing.prototype.getX = function() { return this.x; }; /** * Gets the y position of the Thing. * * @returns {number} The y position of the Thing. */ Thing.prototype.getY = function() { return this.y; }; /** * This function is overridden in subclasses of Thing. */ Thing.prototype.draw = function() { }; /** * Check if a given point is within the Thing. * This function only works in subclasses of Thing. * * @param {number} x - The x coordinate of the point being checked. * @param {number} y - The y coordinate of the point being checked. * @returns {boolean} Whether the point x, y is within the Thing. */ Thing.prototype.containsPoint = function(x, y) { return false; }; module.exports = Thing;