diff --git a/package.json b/package.json index cb9aed4..8c739c0 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "babel-preset-es2015": "^6.18.0", "babel-preset-react": "^6.16.0", "body-parser": "^1.15.2", + "lodash": "^4.17.2", "react": "^15.4.0", "react-dom": "^15.4.0" } diff --git a/src/app/calc.js b/src/app/calc.js new file mode 100644 index 0000000..5b0911e --- /dev/null +++ b/src/app/calc.js @@ -0,0 +1,26 @@ +import should from './should'; + +export default calc = { + numberOfBits: function (num) { + if(num < 0) { + return 32; + } + should.bePositiveInteger(num); + return Math.floor(Math.log(num) / Math.log(2)) + 1; + }, + + maxNumberOfBits: function (arr) { + + var counts = [], num; + for (var i = 0; i < arr.length; i++) { + num = arr[i]; + counts.push(this.numberOfBits(num)); + } + + return Math.max.apply(null, counts); + }, + + calcExpression: function (expr) { + return eval(expr.expressionString); + } + }; \ No newline at end of file diff --git a/src/app/components/results/ListOfNumbersExpressionView.jsx b/src/app/components/results/ListOfNumbersExpressionView.jsx index c98bdea..f687777 100644 --- a/src/app/components/results/ListOfNumbersExpressionView.jsx +++ b/src/app/components/results/ListOfNumbersExpressionView.jsx @@ -1,9 +1,10 @@ import React from 'react'; +import formatter from '../../formatter'; export default class ListOfNumersExpressionView extends React.Component { render() { const expr = this.props.expression; - const numberViews = expr.numbers.map((n, i) => ) + const numberViews = expr.numbers.map((n, i) => ) return {numberViews}
@@ -11,15 +12,43 @@ export default class ListOfNumersExpressionView extends React.Component { } class OperandView extends React.Component { + componentWillMount() { + this.setState(this.props.operand); + } render() { - const op = this.props.operand; - console.log(op); - // const bitsSize = this.propsю; - // .padLeft(m.bitsSize, '0') - return + const op = this.state; + const binaryString = formatter.padLeft(op.bin, this.props.maxBitsLegnth, '0'); + + return {op.input} - {op.bin} + this.flipBit(i)} /> {op.other} }; + + flipBit(index) { + var op = this.props.operand; + const binaryString = formatter.padLeft(op.bin, this.props.maxBitsLegnth, '0'); + var arr = binaryString.split(''); + arr[index] = arr[index] == '0' ? '1' : '0'; + op.update(arr.join('')); + this.setState(op); + } +} + +class ClickableBinary extends React.Component { + render() { + const str = this.props.binaryString; + const chars = str.split(''); + const classNames = { '0': 'zero flipable', '1' : 'one flipable' }; + const children = chars.map((c, i) => this.onBitClick(i, e)}>{c}); + + return {children} + } + + onBitClick(index, e) { + if(this.props.onFlipBit) { + this.props.onFlipBit(index); + } + } } \ No newline at end of file diff --git a/src/app/expression.js b/src/app/expression.js index fae9385..d20d9c1 100644 --- a/src/app/expression.js +++ b/src/app/expression.js @@ -1,3 +1,5 @@ +import * as _ from 'lodash'; + var expression = { factories:[], canParse: function(string) { @@ -119,6 +121,7 @@ export class Operand { this.bin = this.value < 0 ? (this.value >>> 0).toString(2) : this.value.toString(2); this.kind = this.input.indexOf('0x') > -1 ? 'hex' : 'dec'; this.other = this.kind == 'dec' ? this.hex : this.dec; + this.lengthInBits = Operand.getBitLength(this.value); } getLengthInBits() { @@ -128,19 +131,7 @@ export class Operand { return Math.floor(Math.log(this.value) / Math.log(2)) + 1; }; - toKindString(value, kind) { - switch(kind) { - case 'hex': - var hexVal = Math.abs(value).toString(16); - return value >= 0 ? '0x' + hexVal : '-0x' + hexVal; - case 'bin': - return (value>>>0).toString(2); - case 'dec': - return value.toString(10); - default: - throw new Error("Unexpected kind: " + kind) - } - }; + getOtherKind(kind) { switch(kind) { @@ -153,6 +144,17 @@ export class Operand { toString() { return this.input; } + + update(binary) { + this.value = parseInt(2); + this.bin = binary; + this.dec = Operand.toKindString(this.value, 'dec'); + this.hex = Operand.toKindString(this.value, 'hex'); + } + + static getBitLength(num) { + return Math.floor(Math.log(num) / Math.log(2)) + 1 + } static getBase(kind){ switch (kind){ @@ -171,6 +173,20 @@ export class Operand { return new Operand(str); }; + static toKindString(value, kind) { + switch(kind) { + case 'hex': + var hexVal = Math.abs(value).toString(16); + return value >= 0 ? '0x' + hexVal : '-0x' + hexVal; + case 'bin': + return (value>>>0).toString(2); + case 'dec': + return value.toString(10); + default: + throw new Error("Unexpected kind: " + kind) + } + }; + static toHexString (hex) { return hex.indexOf('-') == 0 ? '-0x' + hex.substr(1) : '0x' + hex; }; @@ -223,6 +239,7 @@ export class ListOfNumbersExpression { constructor(expressionString, numbers) { this.expressionString = expressionString; this.numbers = numbers; + this.maxBitsLegnth = _.chain(numbers).map(n => n.lengthInBits).reduce((n , c) => n >= c ? n : c, 0).value(); } } diff --git a/src/app/formatter.js b/src/app/formatter.js new file mode 100644 index 0000000..42dd5ee --- /dev/null +++ b/src/app/formatter.js @@ -0,0 +1,26 @@ +export default { + formatString: function(num, kind) { + return num.toString(getBase(kind || "bin")); + }, + padLeft: function (str, length, symbol) { + var sb = Array.prototype.slice.call(str), symbol = symbol || "0"; + + if(length == null) { + return str; + } + + while(length > sb.length) { + sb.unshift(symbol); + } + + return sb.join(''); + } + }; + + function getBase(kind) { + switch (kind){ + case 'bin': return 2; + case 'hex': return 16; + case 'dec': return 10; + } + } \ No newline at end of file