I'm open to any feedback even if it's just a quick browsing over to get a quick opinion of my code.
As part of a job interview process I was given a coding challenge to complete. The challenge was pretty open and simply said to create a solution that graphed a linear equasion using javascript. Now that I've submitted my solution that I think is pretty well laid out, I wanted to see what kind of feedback I could get from the community about what I might be able to improve about my solution. (Readability, adhering to best practices, design patterns, etc.)
Here is a demo of the solution: https://codepen.io/adozark/full/jwwPNM/
In my solutions I have three files:
equation.js : this file contains a javascript class Equation that takes a string and parses, validates, and runs any linear equation (given everything past "y="). the function yGivenX(int) will output the y for any given x based on the linear equation.
function Equation () {
var equation;
this.setEquation = function(value){
equation = value;
}
this.getEquation = function(){
return equation;
}
this.yGivenX = function (x){
var eqx = equation;
if(!this.validateEq()) return;
//expand coeffecients : 2x -> 2*x
eqx = eqx.replace(/([0-9])x/g,"$1*x");
//fill in the value of x
eqx = eqx.replace(/[xX]/g,x);
var yCordinate = eval(eqx);
return yCordinate;
}
this.validateEq = function (){
var validEquationRegex =
new RegExp('^\\s*(?:(?:(?:[0-9]+(?!\\.))|'
+'(?:[0-9]+\\.[0-9]+))|(?:(?:[0-9]+(?!\\.))'
+'|(?:[0-9]*\\.[0-9]+))*[xX])(?:\\s*[*+\\/-]'
+'\\s*(?:(?:(?:[0-9]+(?!\\.))|(?:[0-9]+\\.'
+'[0-9]+))+|(?:(?:[0-9]+(?!\\.))|(?:[0-9]*'
+'\\.[0-9]+))*[xX]))*\\s*$');
var isValidEq = validEquationRegex.exec(equation);
return isValidEq != null;
}
}// end of Equation
grid.js : this file contains the javascript class Grid, which when instantiated with a constructor taking an Equation and a html Canvas object, provides functions like graphEquation() which will draw the portion of the equation that passes through the html canvas and drawGridLines() which by default will mark every 50 pixels if the interval parameter is left undefined.
function Grid(canvas,equation,interval){
var context = canvas.getContext('2d');
var gridTicksInterval;
if(!interval) gridTicksInterval = 50;
this.DrawGridLines = function(){
context.strokeStyle = 'black';
//x line
context.beginPath();
context.moveTo(0,findAbsoluteY(0));
context.lineTo(canvas.width,findAbsoluteY(0));
context.stroke();
//y line
context.beginPath();
context.moveTo(findAbsoluteX(0),0);
context.lineTo(findAbsoluteX(0),canvas.height);
context.stroke();
context.textAlign="center";
//y labels
var offset = (canvas.height % gridTicksInterval)/2;
for(var i = offset; i <= canvas.height ; i += gridTicksInterval){
var width = context.measureText(i).width;
context.fillStyle = 'white';
context.fillRect(findAbsoluteX(-width/2),i-10,width,10);
context.fillStyle = 'black';
context.strokeStyle = 'black';
context.fillText(findRelativeY(i),findAbsoluteX(0),i);
}
//x labels
var xOffset = (canvas.width % gridTicksInterval)/2;
for(var j = xOffset; j <= canvas.width ; j += gridTicksInterval ){
//a center 0 label was already added by the y labels code.
if(findRelativeX(j) === 0) continue;
context.strokeStyle = 'black';
context.textAlign="center";
context.fillText(findRelativeX(j),j,findAbsoluteY(5));
}
}
this.setGridTicksInterval = function(interval){
gridTicksInterval = interval;
}
this.GraphEquation = function(){
var xMin = -(canvas.width / 2);
var xMax = -xMin;
var yMin = equation.yGivenX(xMin);
var yMax = equation.yGivenX(xMax);
context.beginPath();
context.moveTo(findAbsoluteX(xMin),findAbsoluteY(yMin));
context.lineTo(findAbsoluteX(xMax),findAbsoluteY(yMax));
context.strokeStyle = 'red';
context.stroke();
}
//helper functions
function findAbsoluteX(x){
return x + (canvas.width/2);
}
function findAbsoluteY(y){
return -y + (canvas.height/2);
}
function findRelativeX(x){
return x - (canvas.width/2);
}
function findRelativeY(y){
return -y + (canvas.height/2);
}
}
index.html : this file is just an html file that includes some css, an input box and "Graph!" button, an html canvas, and the instantiation of my javascript classes/functions.
<html>
<head>
<style>
.input{
padding: 10px;
}
.message{
height: 25px;
color: red;
}
.center{
text-align: center;
}
canvas {
background-color: white;
}
body {
margin: 0px;
padding: 0px;
background-color: white;
}
</style>
</head>
<body>
<div id='messageBanner' class='center message'>Enter an equasion to
graph!</div>
<div class = "center input">
y = <input type="text" id="functionTextBox">
<button onclick="clicked()">Graph!</button>
</div>
<div class= "center">
<canvas id="myCanvas" width="640" height="540" ></canvas>
</div>
<script src= "./equation.js"></script>
<script src= "./grid.js"></script>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var messageBanner = document.getElementById('messageBanner');
var functionTextBox = document.getElementById('functionTextBox');
var myEq = new Equation();
var myGrid = new Grid(canvas,myEq);
//draw lines when page loads
myGrid.DrawGridLines();
function clicked(){
myEq.setEquation(functionTextBox.value);
//clear the canvas
context.clearRect(0, 0, canvas.width, canvas.height);
//re-draw grid lines.
myGrid.DrawGridLines();
if(!myEq.validateEq())
{
messageBanner.innerText =
"The equasion must contain only real numbers"
+" and the variable x. You can use multiplication, division,"
+ " addition, and subtraction.";
+" Ex: 5x + 100 * 1.5x"
return;
}
myGrid.GraphEquation();
messageBanner.innerText = "Success!";
}
</script>
</body>
</html>