1
0
mirror of https://github.com/DanilaFe/abacus synced 2026-01-25 08:05:19 +00:00

Compare commits

...

38 Commits

Author SHA1 Message Date
192269ea9a Merge branch 'master' into variable-parsing 2017-08-29 18:11:30 -07:00
f134e5aa04 Merge pull request #5 from DanilaFe/dokka-setup
Add dokka plugin to generate documentation.
2017-08-29 18:09:36 -07:00
ece9f1ae04 Add dokka plugin to generate documentation. 2017-08-27 15:47:32 -07:00
553c7354c1 Account for the new string-only node structure.
The output has to be the same as the user-provided input, as the
tree isn't converted to numbers until evaluation.
2017-08-18 16:31:54 -07:00
50ede6460c Remove Abacus dependency from ShuntingYardParser. 2017-08-18 15:57:48 -07:00
beb583a231 Move number string parsing from the parser into the reducer. 2017-08-18 14:26:33 -07:00
e0ff229df4 Temporarily substitute 0 for variables. 2017-08-18 14:21:48 -07:00
1c751353f1 Lex and parse variables. 2017-08-18 14:21:14 -07:00
0a15043b63 Implement a variable TreeNode. 2017-08-18 14:20:49 -07:00
21e059c1ca Add a new TokenType for variables. 2017-08-18 14:20:37 -07:00
16faceb3cc Add comment to DocumentationType. 2017-08-16 15:38:02 -07:00
251da90d57 Fix problems with scaling on mobile phones. 2017-08-15 01:24:48 -07:00
a7536b198f Add a proper About page. 2017-08-15 01:02:16 -07:00
66bda5db39 Add the download page. 2017-08-15 00:40:28 -07:00
2425adaea5 Remove the rounded borders. 2017-08-15 00:40:21 -07:00
f5d913d527 Change download to link to the Download page. 2017-08-15 00:40:05 -07:00
beae822d76 Move button styling into scss. 2017-08-15 00:31:47 -07:00
bcd3e3b68a Add a home layout. 2017-08-15 00:14:20 -07:00
8b42acfbb1 Change the code font. 2017-08-14 23:42:17 -07:00
952eeac704 Add some style to code. 2017-08-14 22:58:32 -07:00
b57f24854e Add the page layout for pages like About. 2017-08-14 22:58:27 -07:00
6758771c45 Add support for navbar links. 2017-08-14 22:46:39 -07:00
415a05288a Use the center class for centering the content. 2017-08-14 22:36:46 -07:00
334439e075 Add a header. 2017-08-14 22:36:36 -07:00
852776566d Add some basic CSS styling. 2017-08-14 22:36:26 -07:00
07020de1f9 Add the CSS file and link to it from head. 2017-08-14 21:40:37 -07:00
06c2397a09 Use the minima head.html include. 2017-08-14 21:28:28 -07:00
69fe28d5e4 Modify 404 to use the base layout. 2017-08-14 21:22:55 -07:00
367c282497 Start the base page layout. 2017-08-14 21:22:43 -07:00
2876eda2ca Add a new head include. 2017-08-14 21:22:34 -07:00
4ec8c7a535 Remove default theme altogether. 2017-08-14 21:16:35 -07:00
5167946fe2 Overwrite the default header and footer. Temporarily blank. 2017-08-14 21:13:33 -07:00
418e896108 Create the about page. 2017-08-14 21:12:41 -07:00
d3012b9624 Delete the about me page, and add a folder for pages. 2017-08-14 21:11:16 -07:00
bf7881faab Remove the default post. 2017-08-14 19:42:14 -07:00
b75e92838d Configure the default site. 2017-08-14 19:42:06 -07:00
620f087e38 Create basic Jekyll template. 2017-08-14 19:21:17 -07:00
205d5dbc77 Format code. 2017-08-14 19:03:52 -07:00
42 changed files with 732 additions and 283 deletions

View File

@@ -1,9 +1,25 @@
buildscript {
ext.kotlin_version = '1.1.3'
ext.dokka_version = '0.9.15'
repositories {
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
}
}
subprojects { subprojects {
apply plugin: 'java' apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'org.jetbrains.dokka'
repositories { repositories {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {

View File

@@ -1,7 +1,3 @@
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.1.3'
}
dependencies { dependencies {
compile 'com.moandjiezana.toml:toml4j:0.7.1' compile 'com.moandjiezana.toml:toml4j:0.7.1'
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'

View File

@@ -53,7 +53,7 @@ public class Abacus {
numberReducer = new NumberReducer(this); numberReducer = new NumberReducer(this);
this.configuration = new Configuration(configuration); this.configuration = new Configuration(configuration);
LexerTokenizer lexerTokenizer = new LexerTokenizer(); LexerTokenizer lexerTokenizer = new LexerTokenizer();
ShuntingYardParser shuntingYardParser = new ShuntingYardParser(this); ShuntingYardParser shuntingYardParser = new ShuntingYardParser();
treeBuilder = new TreeBuilder<>(lexerTokenizer, shuntingYardParser); treeBuilder = new TreeBuilder<>(lexerTokenizer, shuntingYardParser);
pluginManager.addListener(shuntingYardParser); pluginManager.addListener(shuntingYardParser);

View File

@@ -48,7 +48,7 @@ public class Configuration {
* *
* @param copyFrom the configuration to copy. * @param copyFrom the configuration to copy.
*/ */
public Configuration(Configuration copyFrom){ public Configuration(Configuration copyFrom) {
copyFrom(copyFrom); copyFrom(copyFrom);
} }
@@ -106,7 +106,7 @@ public class Configuration {
* *
* @return the string that represents this configuration. * @return the string that represents this configuration.
*/ */
public String asTomlString(){ public String asTomlString() {
return TOML_WRITER.write(this); return TOML_WRITER.write(this);
} }

View File

@@ -1,5 +1,9 @@
package org.nwapw.abacus.function; package org.nwapw.abacus.function;
/**
* Enum that holds the type of documentation that has been
* registered with Abacus.
*/
public enum DocumentationType { public enum DocumentationType {
FUNCTION FUNCTION

View File

@@ -9,7 +9,7 @@ public class ComputationInterruptedException extends RuntimeException {
/** /**
* Creates a new exception of this type. * Creates a new exception of this type.
*/ */
public ComputationInterruptedException(){ public ComputationInterruptedException() {
super("Computation interrupted by user."); super("Computation interrupted by user.");
} }

View File

@@ -129,7 +129,7 @@ public class NaiveNumber extends NumberInterface {
} }
@Override @Override
public NumberInterface getMaxError(){ public NumberInterface getMaxError() {
return new NaiveNumber(Math.pow(10, -18)); return new NaiveNumber(Math.pow(10, -18));
} }
} }

View File

@@ -9,10 +9,11 @@ public abstract class NumberInterface {
* Check if the thread was interrupted and * Check if the thread was interrupted and
* throw an exception to end the computation. * throw an exception to end the computation.
*/ */
private static void checkInterrupted(){ private static void checkInterrupted() {
if(Thread.currentThread().isInterrupted()) if (Thread.currentThread().isInterrupted())
throw new ComputationInterruptedException(); throw new ComputationInterruptedException();
} }
/** /**
* The maximum precision to which this number operates. * The maximum precision to which this number operates.
* *
@@ -38,7 +39,7 @@ public abstract class NumberInterface {
* @param multiplier the multiplier * @param multiplier the multiplier
* @return the result of the multiplication. * @return the result of the multiplication.
*/ */
public final NumberInterface multiply(NumberInterface multiplier){ public final NumberInterface multiply(NumberInterface multiplier) {
checkInterrupted(); checkInterrupted();
return multiplyInternal(multiplier); return multiplyInternal(multiplier);
} }
@@ -61,7 +62,7 @@ public abstract class NumberInterface {
* @param divisor the divisor * @param divisor the divisor
* @return the result of the division. * @return the result of the division.
*/ */
public final NumberInterface divide(NumberInterface divisor){ public final NumberInterface divide(NumberInterface divisor) {
checkInterrupted(); checkInterrupted();
return divideInternal(divisor); return divideInternal(divisor);
} }
@@ -84,7 +85,7 @@ public abstract class NumberInterface {
* @param summand the summand * @param summand the summand
* @return the result of the summation. * @return the result of the summation.
*/ */
public final NumberInterface add(NumberInterface summand){ public final NumberInterface add(NumberInterface summand) {
checkInterrupted(); checkInterrupted();
return addInternal(summand); return addInternal(summand);
} }
@@ -107,7 +108,7 @@ public abstract class NumberInterface {
* @param subtrahend the subtrahend. * @param subtrahend the subtrahend.
* @return the result of the subtraction. * @return the result of the subtraction.
*/ */
public final NumberInterface subtract(NumberInterface subtrahend){ public final NumberInterface subtract(NumberInterface subtrahend) {
checkInterrupted(); checkInterrupted();
return subtractInternal(subtrahend); return subtractInternal(subtrahend);
} }
@@ -129,7 +130,7 @@ public abstract class NumberInterface {
* *
* @return the new instance. * @return the new instance.
*/ */
public final NumberInterface negate(){ public final NumberInterface negate() {
checkInterrupted(); checkInterrupted();
return negateInternal(); return negateInternal();
} }
@@ -150,7 +151,7 @@ public abstract class NumberInterface {
* @param exponent the exponent to which to take the number. * @param exponent the exponent to which to take the number.
* @return the resulting value. * @return the resulting value.
*/ */
public final NumberInterface intPow(int exponent){ public final NumberInterface intPow(int exponent) {
checkInterrupted(); checkInterrupted();
return intPowInternal(exponent); return intPowInternal(exponent);
} }
@@ -184,7 +185,7 @@ public abstract class NumberInterface {
* *
* @return the least integer bigger or equal to the number. * @return the least integer bigger or equal to the number.
*/ */
public final NumberInterface ceiling(){ public final NumberInterface ceiling() {
checkInterrupted(); checkInterrupted();
return ceilingInternal(); return ceilingInternal();
} }
@@ -203,7 +204,7 @@ public abstract class NumberInterface {
* *
* @return the greatest int smaller than or equal to the number. * @return the greatest int smaller than or equal to the number.
*/ */
public final NumberInterface floor(){ public final NumberInterface floor() {
checkInterrupted(); checkInterrupted();
return floorInternal(); return floorInternal();
} }
@@ -219,9 +220,10 @@ public abstract class NumberInterface {
* Returns the fractional part of the number, specifically x - floor(x). * Returns the fractional part of the number, specifically x - floor(x).
* Also, checks if the thread has been interrupted, * Also, checks if the thread has been interrupted,
* and if so, throws an exception. * and if so, throws an exception.
*
* @return the fractional part of the number. * @return the fractional part of the number.
*/ */
public final NumberInterface fractionalPart(){ public final NumberInterface fractionalPart() {
checkInterrupted(); checkInterrupted();
return fractionalPartInternal(); return fractionalPartInternal();
} }
@@ -260,6 +262,7 @@ public abstract class NumberInterface {
/** /**
* Returns the smallest error this instance can tolerate depending * Returns the smallest error this instance can tolerate depending
* on its precision and value. * on its precision and value.
*
* @return the smallest error that should be permitted in calculations. * @return the smallest error that should be permitted in calculations.
*/ */
public abstract NumberInterface getMaxError(); public abstract NumberInterface getMaxError();

View File

@@ -35,7 +35,7 @@ public class PreciseNumber extends NumberInterface {
/** /**
* MathContext that is actually used in calculations. * MathContext that is actually used in calculations.
*/ */
private static MathContext internalContext = new MathContext(outputContext.getPrecision()+numExtraInternalSigFigs); private static MathContext internalContext = new MathContext(outputContext.getPrecision() + numExtraInternalSigFigs);
/** /**
* The value of the PreciseNumber. * The value of the PreciseNumber.
@@ -129,7 +129,7 @@ public class PreciseNumber extends NumberInterface {
int decimalIndex = str.indexOf('.'); int decimalIndex = str.indexOf('.');
if (decimalIndex != -1) { if (decimalIndex != -1) {
NumberInterface floor = new PreciseNumber(str.substring(0, decimalIndex)); NumberInterface floor = new PreciseNumber(str.substring(0, decimalIndex));
if(signum() == -1){ if (signum() == -1) {
floor = floor.subtract(ONE); floor = floor.subtract(ONE);
} }
return floor; return floor;
@@ -166,7 +166,7 @@ public class PreciseNumber extends NumberInterface {
} }
@Override @Override
public NumberInterface getMaxError(){ public NumberInterface getMaxError() {
return new PreciseNumber(value.ulp()).multiplyInternal(TEN.intPowInternal(value.precision()-internalContext.getPrecision())); return new PreciseNumber(value.ulp()).multiplyInternal(TEN.intPowInternal(value.precision() - internalContext.getPrecision()));
} }
} }

View File

@@ -34,6 +34,7 @@ public class LexerTokenizer implements Tokenizer<Match<TokenType>>, PluginListen
register(" ", TokenType.WHITESPACE); register(" ", TokenType.WHITESPACE);
register(",", TokenType.COMMA); register(",", TokenType.COMMA);
register("[0-9]*(\\.[0-9]+)?", TokenType.NUM); register("[0-9]*(\\.[0-9]+)?", TokenType.NUM);
register("[a-zA-Z]+", TokenType.VARIABLE);
register("\\(", TokenType.OPEN_PARENTH); register("\\(", TokenType.OPEN_PARENTH);
register("\\)", TokenType.CLOSE_PARENTH); register("\\)", TokenType.CLOSE_PARENTH);
}}; }};

View File

@@ -1,6 +1,5 @@
package org.nwapw.abacus.parsing; package org.nwapw.abacus.parsing;
import org.nwapw.abacus.Abacus;
import org.nwapw.abacus.function.Operator; import org.nwapw.abacus.function.Operator;
import org.nwapw.abacus.function.OperatorAssociativity; import org.nwapw.abacus.function.OperatorAssociativity;
import org.nwapw.abacus.function.OperatorType; import org.nwapw.abacus.function.OperatorType;
@@ -17,10 +16,6 @@ import java.util.*;
*/ */
public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListener { public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListener {
/**
* The Abacus instance used to create number instances.
*/
private Abacus abacus;
/** /**
* Map of operator precedences, loaded from the plugin operators. * Map of operator precedences, loaded from the plugin operators.
*/ */
@@ -35,12 +30,9 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
private Map<String, OperatorType> typeMap; private Map<String, OperatorType> typeMap;
/** /**
* Creates a new Shunting Yard parser with the given Abacus instance. * Creates a new Shunting Yard parser.
*
* @param abacus the abacus instance.
*/ */
public ShuntingYardParser(Abacus abacus) { public ShuntingYardParser() {
this.abacus = abacus;
precedenceMap = new HashMap<>(); precedenceMap = new HashMap<>();
associativityMap = new HashMap<>(); associativityMap = new HashMap<>();
typeMap = new HashMap<>(); typeMap = new HashMap<>();
@@ -61,7 +53,7 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
Match<TokenType> match = from.remove(0); Match<TokenType> match = from.remove(0);
previousType = matchType; previousType = matchType;
matchType = match.getType(); matchType = match.getType();
if (matchType == TokenType.NUM) { if (matchType == TokenType.NUM || matchType == TokenType.VARIABLE) {
output.add(match); output.add(match);
} else if (matchType == TokenType.FUNCTION) { } else if (matchType == TokenType.FUNCTION) {
output.add(new Match<>("", TokenType.INTERNAL_FUNCTION_END)); output.add(new Match<>("", TokenType.INTERNAL_FUNCTION_END));
@@ -143,7 +135,9 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
else return new UnaryNode(operator, applyTo); else return new UnaryNode(operator, applyTo);
} }
} else if (matchType == TokenType.NUM) { } else if (matchType == TokenType.NUM) {
return new NumberNode(abacus.numberFromString(match.getContent())); return new NumberNode(match.getContent());
} else if (matchType == TokenType.VARIABLE) {
return new VariableNode(match.getContent());
} else if (matchType == TokenType.FUNCTION) { } else if (matchType == TokenType.FUNCTION) {
String functionName = match.getContent(); String functionName = match.getContent();
FunctionNode node = new FunctionNode(functionName); FunctionNode node = new FunctionNode(functionName);
@@ -162,7 +156,7 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
@Override @Override
public TreeNode constructTree(List<Match<TokenType>> tokens) { public TreeNode constructTree(List<Match<TokenType>> tokens) {
tokens = intoPostfix(new ArrayList<>(tokens)); tokens = intoPostfix(new ArrayList<>(tokens));
if(tokens == null) return null; if (tokens == null) return null;
Collections.reverse(tokens); Collections.reverse(tokens);
TreeNode constructedTree = constructRecursive(tokens); TreeNode constructedTree = constructRecursive(tokens);
return tokens.size() == 0 ? constructedTree : null; return tokens.size() == 0 ? constructedTree : null;

View File

@@ -6,10 +6,6 @@ import org.nwapw.abacus.function.Function;
import org.nwapw.abacus.function.Operator; import org.nwapw.abacus.function.Operator;
import org.nwapw.abacus.number.NumberInterface; import org.nwapw.abacus.number.NumberInterface;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/** /**
* A plugin class that can be externally implemented and loaded via the * A plugin class that can be externally implemented and loaded via the
* plugin manager. Plugins provide functionality to the calculator * plugin manager. Plugins provide functionality to the calculator
@@ -99,9 +95,10 @@ public abstract class Plugin {
/** /**
* To be used in load(). Registers a documentation instance * To be used in load(). Registers a documentation instance
* used to explain some element of the plugin to the user. * used to explain some element of the plugin to the user.
*
* @param documentation the documentation instance. * @param documentation the documentation instance.
*/ */
protected final void registerDocumentation(Documentation documentation){ protected final void registerDocumentation(Documentation documentation) {
manager.registerDocumentation(documentation); manager.registerDocumentation(documentation);
} }
@@ -148,7 +145,7 @@ public abstract class Plugin {
* @param type the type of documentation to search for. * @param type the type of documentation to search for.
* @return the found documentation, or null if none was found. * @return the found documentation, or null if none was found.
*/ */
protected final Documentation documentationFor(String name, DocumentationType type){ protected final Documentation documentationFor(String name, DocumentationType type) {
return manager.documentationFor(name, type); return manager.documentationFor(name, type);
} }

View File

@@ -8,7 +8,10 @@ import org.nwapw.abacus.function.Operator;
import org.nwapw.abacus.number.NumberInterface; import org.nwapw.abacus.number.NumberInterface;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.*; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/** /**
* A class that controls instances of plugins, allowing for them * A class that controls instances of plugins, allowing for them
@@ -79,82 +82,90 @@ public class PluginManager {
/** /**
* Registers a function under the given name. * Registers a function under the given name.
* @param name the name of the function. *
* @param name the name of the function.
* @param function the function to register. * @param function the function to register.
*/ */
public void registerFunction(String name, Function function){ public void registerFunction(String name, Function function) {
registeredFunctions.put(name, function); registeredFunctions.put(name, function);
} }
/** /**
* Registers an operator under the given name. * Registers an operator under the given name.
* @param name the name of the operator. *
* @param name the name of the operator.
* @param operator the operator to register. * @param operator the operator to register.
*/ */
public void registerOperator(String name, Operator operator){ public void registerOperator(String name, Operator operator) {
registeredOperators.put(name, operator); registeredOperators.put(name, operator);
} }
/** /**
* Registers a number implementation under the given name. * Registers a number implementation under the given name.
* @param name the name of the number implementation. *
* @param name the name of the number implementation.
* @param implementation the number implementation to register. * @param implementation the number implementation to register.
*/ */
public void registerNumberImplementation(String name, NumberImplementation implementation){ public void registerNumberImplementation(String name, NumberImplementation implementation) {
registeredNumberImplementations.put(name, implementation); registeredNumberImplementations.put(name, implementation);
} }
/** /**
* Registers the given documentation with the plugin manager, * Registers the given documentation with the plugin manager,
* making it accessible to the plugin manager etc. * making it accessible to the plugin manager etc.
*
* @param documentation the documentation to register. * @param documentation the documentation to register.
*/ */
public void registerDocumentation(Documentation documentation){ public void registerDocumentation(Documentation documentation) {
registeredDocumentation.add(documentation); registeredDocumentation.add(documentation);
} }
/** /**
* Gets the function registered under the given name. * Gets the function registered under the given name.
*
* @param name the name of the function. * @param name the name of the function.
* @return the function, or null if it was not found. * @return the function, or null if it was not found.
*/ */
public Function functionFor(String name){ public Function functionFor(String name) {
return registeredFunctions.get(name); return registeredFunctions.get(name);
} }
/** /**
* Gets the operator registered under the given name. * Gets the operator registered under the given name.
*
* @param name the name of the operator. * @param name the name of the operator.
* @return the operator, or null if it was not found. * @return the operator, or null if it was not found.
*/ */
public Operator operatorFor(String name){ public Operator operatorFor(String name) {
return registeredOperators.get(name); return registeredOperators.get(name);
} }
/** /**
* Gets the number implementation registered under the given name. * Gets the number implementation registered under the given name.
*
* @param name the name of the number implementation. * @param name the name of the number implementation.
* @return the number implementation, or null if it was not found. * @return the number implementation, or null if it was not found.
*/ */
public NumberImplementation numberImplementationFor(String name){ public NumberImplementation numberImplementationFor(String name) {
return registeredNumberImplementations.get(name); return registeredNumberImplementations.get(name);
} }
/** /**
* Gets the documentation for the given entity of the given type. * Gets the documentation for the given entity of the given type.
*
* @param name the name of the entity to search for. * @param name the name of the entity to search for.
* @param type the type that this entity is, to filter out similarly named documentation. * @param type the type that this entity is, to filter out similarly named documentation.
* @return the documentation object. * @return the documentation object.
*/ */
public Documentation documentationFor(String name, DocumentationType type){ public Documentation documentationFor(String name, DocumentationType type) {
Documentation toReturn = null; Documentation toReturn = null;
for(Documentation entry : registeredDocumentation){ for (Documentation entry : registeredDocumentation) {
if(entry.getCodeName().equals(name) && entry.getType() == type) { if (entry.getCodeName().equals(name) && entry.getType() == type) {
toReturn = entry; toReturn = entry;
break; break;
} }
} }
if(toReturn == null){ if (toReturn == null) {
toReturn = new Documentation(name, "", "", "", type); toReturn = new Documentation(name, "", "", "", type);
registerDocumentation(toReturn); registerDocumentation(toReturn);
} }
@@ -170,9 +181,9 @@ public class PluginManager {
public NumberImplementation interfaceImplementationFor(Class<? extends NumberInterface> name) { public NumberImplementation interfaceImplementationFor(Class<? extends NumberInterface> name) {
if (cachedInterfaceImplementations.containsKey(name)) return cachedInterfaceImplementations.get(name); if (cachedInterfaceImplementations.containsKey(name)) return cachedInterfaceImplementations.get(name);
NumberImplementation toReturn = null; NumberImplementation toReturn = null;
for(String key : registeredNumberImplementations.keySet()){ for (String key : registeredNumberImplementations.keySet()) {
NumberImplementation implementation = registeredNumberImplementations.get(key); NumberImplementation implementation = registeredNumberImplementations.get(key);
if(implementation.getImplementation() == name) { if (implementation.getImplementation() == name) {
toReturn = implementation; toReturn = implementation;
break; break;
} }
@@ -226,10 +237,11 @@ public class PluginManager {
/** /**
* Removes the plugin with the given class from the manager. * Removes the plugin with the given class from the manager.
*
* @param toRemove the plugin to remove. * @param toRemove the plugin to remove.
*/ */
public void removeClass(Class<? extends Plugin> toRemove){ public void removeClass(Class<? extends Plugin> toRemove) {
if(!loadedPluginClasses.contains(toRemove)) return; if (!loadedPluginClasses.contains(toRemove)) return;
plugins.removeIf(plugin -> plugin.getClass() == toRemove); plugins.removeIf(plugin -> plugin.getClass() == toRemove);
loadedPluginClasses.remove(toRemove); loadedPluginClasses.remove(toRemove);
} }
@@ -237,7 +249,7 @@ public class PluginManager {
/** /**
* Removes all plugins from this plugin manager. * Removes all plugins from this plugin manager.
*/ */
public void removeAll(){ public void removeAll() {
loadedPluginClasses.clear(); loadedPluginClasses.clear();
plugins.clear(); plugins.clear();
} }

View File

@@ -1,19 +1,12 @@
package org.nwapw.abacus.plugin; package org.nwapw.abacus.plugin;
import org.nwapw.abacus.function.*; import org.nwapw.abacus.function.*;
import org.nwapw.abacus.lexing.pattern.Match;
import org.nwapw.abacus.number.NaiveNumber; import org.nwapw.abacus.number.NaiveNumber;
import org.nwapw.abacus.number.NumberInterface; import org.nwapw.abacus.number.NumberInterface;
import org.nwapw.abacus.number.PreciseNumber; import org.nwapw.abacus.number.PreciseNumber;
import org.nwapw.abacus.parsing.Parser;
import org.nwapw.abacus.parsing.ShuntingYardParser;
import org.nwapw.abacus.tree.TokenType;
import org.nwapw.abacus.tree.TreeNode;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.function.BiFunction; import java.util.function.BiFunction;
/** /**
@@ -22,11 +15,6 @@ import java.util.function.BiFunction;
*/ */
public class StandardPlugin extends Plugin { public class StandardPlugin extends Plugin {
/**
* Stores objects of NumberInterface with integer values for reuse.
*/
private final static HashMap<Class<? extends NumberInterface>, HashMap<Integer, NumberInterface>> integerValues = new HashMap<>();
/** /**
* The addition operator, + * The addition operator, +
*/ */
@@ -92,6 +80,75 @@ public class StandardPlugin extends Plugin {
return product; return product;
} }
}); });
/**
* The combination operator.
*/
public static final Operator OP_NCR = new Operator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 0, new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 2 && params[0].fractionalPart().signum() == 0
&& params[1].fractionalPart().signum() == 0;
}
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
return OP_NPR.getFunction().apply(params).divide(OP_FACTORIAL.getFunction().apply(params[1]));
}
});
/**
* The implementation for double-based naive numbers.
*/
public static final NumberImplementation IMPLEMENTATION_NAIVE = new NumberImplementation(NaiveNumber.class, 0) {
@Override
public NumberInterface instanceForString(String string) {
return new NaiveNumber(string);
}
@Override
public NumberInterface instanceForPi() {
return new NaiveNumber(Math.PI);
}
};
/**
* The implementation for the infinite-precision BigDecimal.
*/
public static final NumberImplementation IMPLEMENTATION_PRECISE = new NumberImplementation(PreciseNumber.class, 0) {
@Override
public NumberInterface instanceForString(String string) {
return new PreciseNumber(string);
}
@Override
public NumberInterface instanceForPi() {
NumberInterface C = FUNCTION_SQRT.apply(new PreciseNumber("10005")).multiply(new PreciseNumber("426880"));
NumberInterface M = PreciseNumber.ONE;
NumberInterface L = new PreciseNumber("13591409");
NumberInterface X = M;
NumberInterface sum = L;
int termsNeeded = C.getMaxPrecision() / 13 + 1;
NumberInterface lSummand = new PreciseNumber("545140134");
NumberInterface xMultiplier = new PreciseNumber("262537412")
.multiply(new PreciseNumber("1000000000"))
.add(new PreciseNumber("640768000"))
.negate();
for (int i = 0; i < termsNeeded; i++) {
M = M
.multiply(new PreciseNumber((12 * i + 2) + ""))
.multiply(new PreciseNumber((12 * i + 6) + ""))
.multiply(new PreciseNumber((12 * i + 10) + ""))
.divide(new PreciseNumber(Math.pow(i + 1, 3) + ""));
L = L.add(lSummand);
X = X.multiply(xMultiplier);
sum = sum.add(M.multiply(L).divide(X));
}
return C.divide(sum);
}
};
/**
* Stores objects of NumberInterface with integer values for reuse.
*/
private final static HashMap<Class<? extends NumberInterface>, HashMap<Integer, NumberInterface>> integerValues = new HashMap<>();
/** /**
* The division operator, / * The division operator, /
*/ */
@@ -150,17 +207,17 @@ public class StandardPlugin extends Plugin {
@Override @Override
protected NumberInterface applyInternal(NumberInterface[] params) { protected NumberInterface applyInternal(NumberInterface[] params) {
if(params[0].compareTo(params[1]) < 0 || if (params[0].compareTo(params[1]) < 0 ||
params[0].signum() < 0 || params[0].signum() < 0 ||
(params[0].signum() == 0 && params[1].signum() != 0)) return fromInt(params[0].getClass(), 0); (params[0].signum() == 0 && params[1].signum() != 0)) return fromInt(params[0].getClass(), 0);
NumberInterface total = fromInt(params[0].getClass(), 1); NumberInterface total = fromInt(params[0].getClass(), 1);
NumberInterface multiplyBy = params[0]; NumberInterface multiplyBy = params[0];
NumberInterface remainingMultiplications = params[1]; NumberInterface remainingMultiplications = params[1];
NumberInterface halfway = params[0].divide(fromInt(params[0].getClass(), 2)); NumberInterface halfway = params[0].divide(fromInt(params[0].getClass(), 2));
if(remainingMultiplications.compareTo(halfway) > 0){ if (remainingMultiplications.compareTo(halfway) > 0) {
remainingMultiplications = params[0].subtract(remainingMultiplications); remainingMultiplications = params[0].subtract(remainingMultiplications);
} }
while(remainingMultiplications.signum() > 0){ while (remainingMultiplications.signum() > 0) {
total = total.multiply(multiplyBy); total = total.multiply(multiplyBy);
remainingMultiplications = remainingMultiplications.subtract(fromInt(params[0].getClass(), 1)); remainingMultiplications = remainingMultiplications.subtract(fromInt(params[0].getClass(), 1));
multiplyBy = multiplyBy.subtract(fromInt(params[0].getClass(), 1)); multiplyBy = multiplyBy.subtract(fromInt(params[0].getClass(), 1));
@@ -168,21 +225,6 @@ public class StandardPlugin extends Plugin {
return total; return total;
} }
}); });
/**
* The combination operator.
*/
public static final Operator OP_NCR = new Operator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 0, new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 2 && params[0].fractionalPart().signum() == 0
&& params[1].fractionalPart().signum() == 0;
}
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
return OP_NPR.getFunction().apply(params).divide(OP_FACTORIAL.getFunction().apply(params[1]));
}
});
/** /**
* The absolute value function, abs(-3) = 3 * The absolute value function, abs(-3) = 3
*/ */
@@ -277,20 +319,6 @@ public class StandardPlugin extends Plugin {
return sum; return sum;
} }
}; };
/**
* The square root function.
*/
public static final Function FUNCTION_SQRT = new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 1;
}
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
return OP_CARET.getFunction().apply(params[0], ((new NaiveNumber(0.5)).promoteTo(params[0].getClass())));
}
};
/** /**
* Gets a random number smaller or equal to the given number's integer value. * Gets a random number smaller or equal to the given number's integer value.
*/ */
@@ -305,94 +333,6 @@ public class StandardPlugin extends Plugin {
return fromInt(params[0].getClass(), (int) Math.round(Math.random() * params[0].floor().intValue())); return fromInt(params[0].getClass(), (int) Math.round(Math.random() * params[0].floor().intValue()));
} }
}; };
/**
* The implementation for double-based naive numbers.
*/
public static final NumberImplementation IMPLEMENTATION_NAIVE = new NumberImplementation(NaiveNumber.class, 0) {
@Override
public NumberInterface instanceForString(String string) {
return new NaiveNumber(string);
}
@Override
public NumberInterface instanceForPi() {
return new NaiveNumber(Math.PI);
}
};
/**
* The implementation for the infinite-precision BigDecimal.
*/
public static final NumberImplementation IMPLEMENTATION_PRECISE = new NumberImplementation(PreciseNumber.class, 0) {
@Override
public NumberInterface instanceForString(String string) {
return new PreciseNumber(string);
}
@Override
public NumberInterface instanceForPi() {
NumberInterface C = FUNCTION_SQRT.apply(new PreciseNumber("10005")).multiply(new PreciseNumber("426880"));
NumberInterface M = PreciseNumber.ONE;
NumberInterface L = new PreciseNumber("13591409");
NumberInterface X = M;
NumberInterface sum = L;
int termsNeeded = C.getMaxPrecision() / 13 + 1;
NumberInterface lSummand = new PreciseNumber("545140134");
NumberInterface xMultiplier = new PreciseNumber("262537412")
.multiply(new PreciseNumber("1000000000"))
.add(new PreciseNumber("640768000"))
.negate();
for (int i = 0; i < termsNeeded; i++) {
M = M
.multiply(new PreciseNumber((12 * i + 2) + ""))
.multiply(new PreciseNumber((12 * i + 6) + ""))
.multiply(new PreciseNumber((12 * i + 10) + ""))
.divide(new PreciseNumber(Math.pow(i + 1, 3) + ""));
L = L.add(lSummand);
X = X.multiply(xMultiplier);
sum = sum.add(M.multiply(L).divide(X));
}
return C.divide(sum);
}
};
private static final HashMap<Class<? extends NumberInterface>, ArrayList<NumberInterface>> FACTORIAL_LISTS = new HashMap<>();
/**
* The exponential function, exp(1) = e^1 = 2.71...
*/
public static final Function FUNCTION_EXP = new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 1;
}
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
NumberInterface maxError = params[0].getMaxError();
int n = 0;
if (params[0].signum() < 0) {
NumberInterface[] negatedParams = {params[0].negate()};
return fromInt(params[0].getClass(), 1).divide(applyInternal(negatedParams));
} else {
//We need n such that x^(n+1) * 3^ceil(x) <= maxError * (n+1)!.
//right and left refer to lhs and rhs in the above inequality.
NumberInterface sum = fromInt(params[0].getClass(), 1);
NumberInterface nextNumerator = params[0];
NumberInterface left = params[0].multiply(fromInt(params[0].getClass(), 3).intPow(params[0].ceiling().intValue())), right = maxError;
do {
sum = sum.add(nextNumerator.divide(factorial(params[0].getClass(), n + 1)));
n++;
nextNumerator = nextNumerator.multiply(params[0]);
left = left.multiply(params[0]);
NumberInterface nextN = fromInt(params[0].getClass(), n + 1);
right = right.multiply(nextN);
//System.out.println(left + ", " + right);
}
while (left.compareTo(right) > 0);
//System.out.println(n+1);
return sum;
}
}
};
/** /**
* The caret / pow operator, ^ * The caret / pow operator, ^
*/ */
@@ -414,15 +354,67 @@ public class StandardPlugin extends Plugin {
else if (params[1].compareTo(zero) == 0) else if (params[1].compareTo(zero) == 0)
return fromInt(params[0].getClass(), 1); return fromInt(params[0].getClass(), 1);
//Detect integer bases: //Detect integer bases:
if(params[0].fractionalPart().compareTo(fromInt(params[0].getClass(), 0)) == 0 if (params[0].fractionalPart().compareTo(fromInt(params[0].getClass(), 0)) == 0
&& FUNCTION_ABS.apply(params[1]).compareTo(fromInt(params[0].getClass(), Integer.MAX_VALUE)) < 0 && FUNCTION_ABS.apply(params[1]).compareTo(fromInt(params[0].getClass(), Integer.MAX_VALUE)) < 0
&& FUNCTION_ABS.apply(params[1]).compareTo(fromInt(params[1].getClass(), 1)) >= 0){ && FUNCTION_ABS.apply(params[1]).compareTo(fromInt(params[1].getClass(), 1)) >= 0) {
NumberInterface[] newParams = {params[0], params[1].fractionalPart()}; NumberInterface[] newParams = {params[0], params[1].fractionalPart()};
return params[0].intPow(params[1].floor().intValue()).multiply(applyInternal(newParams)); return params[0].intPow(params[1].floor().intValue()).multiply(applyInternal(newParams));
} }
return FUNCTION_EXP.apply(FUNCTION_LN.apply(FUNCTION_ABS.apply(params[0])).multiply(params[1])); return FUNCTION_EXP.apply(FUNCTION_LN.apply(FUNCTION_ABS.apply(params[0])).multiply(params[1]));
} }
}); });
/**
* The square root function.
*/
public static final Function FUNCTION_SQRT = new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 1;
}
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
return OP_CARET.getFunction().apply(params[0], ((new NaiveNumber(0.5)).promoteTo(params[0].getClass())));
}
};
private static final HashMap<Class<? extends NumberInterface>, ArrayList<NumberInterface>> FACTORIAL_LISTS = new HashMap<>();
/**
* The exponential function, exp(1) = e^1 = 2.71...
*/
public static final Function FUNCTION_EXP = new Function() {
@Override
protected boolean matchesParams(NumberInterface[] params) {
return params.length == 1;
}
@Override
protected NumberInterface applyInternal(NumberInterface[] params) {
NumberInterface maxError = params[0].getMaxError();
int n = 0;
if (params[0].signum() < 0) {
NumberInterface[] negatedParams = {params[0].negate()};
return fromInt(params[0].getClass(), 1).divide(applyInternal(negatedParams));
} else {
//We need n such that x^(n+1) * 3^ceil(x) <= maxError * (n+1)!.
//right and left refer to lhs and rhs in the above inequality.
NumberInterface sum = fromInt(params[0].getClass(), 1);
NumberInterface nextNumerator = params[0];
NumberInterface left = params[0].multiply(fromInt(params[0].getClass(), 3).intPow(params[0].ceiling().intValue())), right = maxError;
do {
sum = sum.add(nextNumerator.divide(factorial(params[0].getClass(), n + 1)));
n++;
nextNumerator = nextNumerator.multiply(params[0]);
left = left.multiply(params[0]);
NumberInterface nextN = fromInt(params[0].getClass(), n + 1);
right = right.multiply(nextN);
//System.out.println(left + ", " + right);
}
while (left.compareTo(right) > 0);
//System.out.println(n+1);
return sum;
}
}
};
/** /**
* The sine function (the argument is interpreted in radians). * The sine function (the argument is interpreted in radians).
*/ */
@@ -531,7 +523,7 @@ public class StandardPlugin extends Plugin {
@Override @Override
protected NumberInterface applyInternal(NumberInterface[] params) { protected NumberInterface applyInternal(NumberInterface[] params) {
if(FUNCTION_ABS.apply(params[0]).compareTo(new NaiveNumber(0.8).promoteTo(params[0].getClass())) >= 0){ if (FUNCTION_ABS.apply(params[0]).compareTo(new NaiveNumber(0.8).promoteTo(params[0].getClass())) >= 0) {
NumberInterface[] newParams = {FUNCTION_SQRT.apply(fromInt(params[0].getClass(), 1).subtract(params[0].multiply(params[0])))}; NumberInterface[] newParams = {FUNCTION_SQRT.apply(fromInt(params[0].getClass(), 1).subtract(params[0].multiply(params[0])))};
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2)) return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
.subtract(applyInternal(newParams)).multiply(fromInt(params[0].getClass(), params[0].signum())); .subtract(applyInternal(newParams)).multiply(fromInt(params[0].getClass(), params[0].signum()));
@@ -540,10 +532,10 @@ public class StandardPlugin extends Plugin {
multiplier = currentTerm.multiply(currentTerm), summandBound = sum.getMaxError().multiply(fromInt(sum.getClass(), 1).subtract(multiplier)), multiplier = currentTerm.multiply(currentTerm), summandBound = sum.getMaxError().multiply(fromInt(sum.getClass(), 1).subtract(multiplier)),
power = currentTerm, coefficient = fromInt(params[0].getClass(), 1); power = currentTerm, coefficient = fromInt(params[0].getClass(), 1);
int exponent = 1; int exponent = 1;
while(FUNCTION_ABS.apply(currentTerm).compareTo(summandBound) > 0){ while (FUNCTION_ABS.apply(currentTerm).compareTo(summandBound) > 0) {
exponent += 2; exponent += 2;
power = power.multiply(multiplier); power = power.multiply(multiplier);
coefficient = coefficient.multiply(fromInt(params[0].getClass(), exponent-2)) coefficient = coefficient.multiply(fromInt(params[0].getClass(), exponent - 2))
.divide(fromInt(params[0].getClass(), exponent - 1)); .divide(fromInt(params[0].getClass(), exponent - 1));
currentTerm = power.multiply(coefficient).divide(fromInt(power.getClass(), exponent)); currentTerm = power.multiply(coefficient).divide(fromInt(power.getClass(), exponent));
sum = sum.add(currentTerm); sum = sum.add(currentTerm);
@@ -611,27 +603,27 @@ public class StandardPlugin extends Plugin {
@Override @Override
protected NumberInterface applyInternal(NumberInterface[] params) { protected NumberInterface applyInternal(NumberInterface[] params) {
if(params[0].signum() == -1){ if (params[0].signum() == -1) {
NumberInterface[] negatedParams = {params[0].negate()}; NumberInterface[] negatedParams = {params[0].negate()};
return applyInternal(negatedParams).negate(); return applyInternal(negatedParams).negate();
} }
if(params[0].compareTo(fromInt(params[0].getClass(), 1)) > 0){ if (params[0].compareTo(fromInt(params[0].getClass(), 1)) > 0) {
NumberInterface[] reciprocalParams = {fromInt(params[0].getClass(), 1).divide(params[0])}; NumberInterface[] reciprocalParams = {fromInt(params[0].getClass(), 1).divide(params[0])};
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2)) return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 2))
.subtract(applyInternal(reciprocalParams)); .subtract(applyInternal(reciprocalParams));
} }
if(params[0].compareTo(fromInt(params[0].getClass(), 1)) == 0){ if (params[0].compareTo(fromInt(params[0].getClass(), 1)) == 0) {
return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 4)); return piFor(params[0].getClass()).divide(fromInt(params[0].getClass(), 4));
} }
if(params[0].compareTo(new NaiveNumber(0.9).promoteTo(params[0].getClass())) >= 0){ if (params[0].compareTo(new NaiveNumber(0.9).promoteTo(params[0].getClass())) >= 0) {
NumberInterface[] newParams = {params[0].multiply(fromInt(params[0].getClass(),2 )) NumberInterface[] newParams = {params[0].multiply(fromInt(params[0].getClass(), 2))
.divide(fromInt(params[0].getClass(), 1).subtract(params[0].multiply(params[0])))}; .divide(fromInt(params[0].getClass(), 1).subtract(params[0].multiply(params[0])))};
return applyInternal(newParams).divide(fromInt(params[0].getClass(), 2)); return applyInternal(newParams).divide(fromInt(params[0].getClass(), 2));
} }
NumberInterface currentPower = params[0], currentTerm = currentPower, sum = currentTerm, NumberInterface currentPower = params[0], currentTerm = currentPower, sum = currentTerm,
maxError = params[0].getMaxError(), multiplier = currentPower.multiply(currentPower).negate(); maxError = params[0].getMaxError(), multiplier = currentPower.multiply(currentPower).negate();
int n = 1; int n = 1;
while(FUNCTION_ABS.apply(currentTerm).compareTo(maxError) > 0){ while (FUNCTION_ABS.apply(currentTerm).compareTo(maxError) > 0) {
n += 2; n += 2;
currentPower = currentPower.multiply(multiplier); currentPower = currentPower.multiply(multiplier);
currentTerm = currentPower.divide(fromInt(currentPower.getClass(), n)); currentTerm = currentPower.divide(fromInt(currentPower.getClass(), n));
@@ -737,15 +729,16 @@ public class StandardPlugin extends Plugin {
/** /**
* Returns a number of class numType with value n. * Returns a number of class numType with value n.
*
* @param numType class of number to return. * @param numType class of number to return.
* @param n value of returned number. * @param n value of returned number.
* @return numClass instance with value n. * @return numClass instance with value n.
*/ */
private static NumberInterface fromInt(Class<? extends NumberInterface> numType, int n){ private static NumberInterface fromInt(Class<? extends NumberInterface> numType, int n) {
if(!integerValues.containsKey(numType)){ if (!integerValues.containsKey(numType)) {
integerValues.put(numType, new HashMap<>()); integerValues.put(numType, new HashMap<>());
} }
if(!integerValues.get(numType).containsKey(n)){ if (!integerValues.get(numType).containsKey(n)) {
integerValues.get(numType).put(n, new NaiveNumber(n).promoteTo(numType)); integerValues.get(numType).put(n, new NaiveNumber(n).promoteTo(numType));
} }
return integerValues.get(numType).get(n); return integerValues.get(numType).get(n);

View File

@@ -27,7 +27,9 @@ public class NumberReducer implements Reducer<NumberInterface> {
@Override @Override
public NumberInterface reduceNode(TreeNode node, Object... children) { public NumberInterface reduceNode(TreeNode node, Object... children) {
if (node instanceof NumberNode) { if (node instanceof NumberNode) {
return ((NumberNode) node).getNumber(); return abacus.numberFromString(((NumberNode) node).getNumber());
} else if(node instanceof VariableNode) {
return abacus.numberFromString("0");
} else if (node instanceof BinaryNode) { } else if (node instanceof BinaryNode) {
NumberInterface left = (NumberInterface) children[0]; NumberInterface left = (NumberInterface) children[0];
NumberInterface right = (NumberInterface) children[1]; NumberInterface right = (NumberInterface) children[1];

View File

@@ -7,7 +7,7 @@ package org.nwapw.abacus.tree;
public enum TokenType { public enum TokenType {
INTERNAL_FUNCTION_END(-1), INTERNAL_FUNCTION_END(-1),
ANY(0), WHITESPACE(1), COMMA(2), OP(3), NUM(4), FUNCTION(5), OPEN_PARENTH(6), CLOSE_PARENTH(7); ANY(0), WHITESPACE(1), COMMA(2), OP(3), NUM(4), VARIABLE(5), FUNCTION(6), OPEN_PARENTH(7), CLOSE_PARENTH(8);
/** /**
* The priority by which this token gets sorted. * The priority by which this token gets sorted.

View File

@@ -36,7 +36,7 @@ data class FunctionNode(val function: String) : TreeNode() {
* *
* @node the node to append. * @node the node to append.
*/ */
fun appendChild(node: TreeNode){ fun appendChild(node: TreeNode) {
children.add(node) children.add(node)
} }
@@ -45,7 +45,7 @@ data class FunctionNode(val function: String) : TreeNode() {
* *
* @node the node to prepend. * @node the node to prepend.
*/ */
fun prependChild(node: TreeNode){ fun prependChild(node: TreeNode) {
children.add(0, node) children.add(0, node)
} }

View File

@@ -10,14 +10,14 @@ import org.nwapw.abacus.number.NumberInterface
* *
* @number the number value of this node. * @number the number value of this node.
*/ */
data class NumberNode(val number: NumberInterface) : TreeNode() { data class NumberNode(val number: String) : TreeNode() {
override fun <T : Any> reduce(reducer: Reducer<T>): T? { override fun <T : Any> reduce(reducer: Reducer<T>): T? {
return reducer.reduceNode(this) return reducer.reduceNode(this)
} }
override fun toString(): String { override fun toString(): String {
return number.toString() return number
} }
} }

View File

@@ -6,7 +6,7 @@ package org.nwapw.abacus.tree
* The reducer walks the tree, visiting the children first, converting them into * The reducer walks the tree, visiting the children first, converting them into
* a value, and then attempts to reduce the parent. Eventually, the single final value is returned. * a value, and then attempts to reduce the parent. Eventually, the single final value is returned.
*/ */
interface Reducer <out T> { interface Reducer<out T> {
/** /**
* Reduces the given tree node, given its already reduced children. * Reduces the given tree node, given its already reduced children.
@@ -14,6 +14,6 @@ interface Reducer <out T> {
* @param treeNode the tree node to reduce. * @param treeNode the tree node to reduce.
* @param children the list of children, of type T. * @param children the list of children, of type T.
*/ */
fun reduceNode(treeNode: TreeNode, vararg children: Any) : T? fun reduceNode(treeNode: TreeNode, vararg children: Any): T?
} }

View File

@@ -5,6 +5,6 @@ package org.nwapw.abacus.tree
*/ */
abstract class TreeNode { abstract class TreeNode {
abstract fun <T: Any> reduce(reducer: Reducer<T>) : T? abstract fun <T : Any> reduce(reducer: Reducer<T>): T?
} }

View File

@@ -0,0 +1,21 @@
package org.nwapw.abacus.tree
/**
* A tree node that holds a placeholder variable.
*
* This node holds a variable string, and acts similarly to a number,
* with the key difference of not actually holding a value at runtime.
*
* @param variable the actual variable name that this node represents.
*/
data class VariableNode(val variable: String) : TreeNode() {
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
return reducer.reduceNode(this)
}
override fun toString(): String {
return variable
}
}

View File

@@ -14,12 +14,12 @@ public class CalculationTests {
private static Abacus abacus = new Abacus(new Configuration(0, "precise", new String[]{})); private static Abacus abacus = new Abacus(new Configuration(0, "precise", new String[]{}));
@BeforeClass @BeforeClass
public static void prepareTests(){ public static void prepareTests() {
abacus.getPluginManager().addInstantiated(new StandardPlugin(abacus.getPluginManager())); abacus.getPluginManager().addInstantiated(new StandardPlugin(abacus.getPluginManager()));
abacus.getPluginManager().load(); abacus.getPluginManager().load();
} }
private void testOutput(String input, String parseOutput, String output){ private void testOutput(String input, String parseOutput, String output) {
TreeNode parsedTree = abacus.parseString(input); TreeNode parsedTree = abacus.parseString(input);
Assert.assertNotNull(parsedTree); Assert.assertNotNull(parsedTree);
Assert.assertEquals(parsedTree.toString(), parseOutput); Assert.assertEquals(parsedTree.toString(), parseOutput);
@@ -28,7 +28,7 @@ public class CalculationTests {
Assert.assertTrue(result.toString().startsWith(output)); Assert.assertTrue(result.toString().startsWith(output));
} }
private void testEvalError(String input, String parseOutput){ private void testEvalError(String input, String parseOutput) {
TreeNode parsedTree = abacus.parseString(input); TreeNode parsedTree = abacus.parseString(input);
Assert.assertNotNull(parsedTree); Assert.assertNotNull(parsedTree);
Assert.assertEquals(parsedTree.toString(), parseOutput); Assert.assertEquals(parsedTree.toString(), parseOutput);
@@ -36,56 +36,56 @@ public class CalculationTests {
} }
@Test @Test
public void testAddition(){ public void testAddition() {
testOutput("9.5+10", "(9.5+10)", "19.5"); testOutput("9.5+10", "(9.5+10)", "19.5");
} }
@Test @Test
public void testSubtraction(){ public void testSubtraction() {
testOutput("9.5-10", "(9.5-10)", "-0.5"); testOutput("9.5-10", "(9.5-10)", "-0.5");
} }
@Test @Test
public void testMultiplication(){ public void testMultiplication() {
testOutput("9.5*10", "(9.5*10)", "95"); testOutput("9.5*10", "(9.5*10)", "95");
} }
@Test @Test
public void testDivision(){ public void testDivision() {
testOutput("9.5/2", "(9.5/2)", "4.75"); testOutput("9.5/2", "(9.5/2)", "4.75");
} }
@Test @Test
public void testNegation(){ public void testNegation() {
testOutput("-9.5", "(9.5)`", "-9.5"); testOutput("-9.5", "(9.5)`", "-9.5");
} }
@Test @Test
public void testFactorial(){ public void testFactorial() {
testOutput("7!", "(7)!", "5040"); testOutput("7!", "(7)!", "5040");
} }
@Test @Test
public void testAbs(){ public void testAbs() {
testOutput("abs(-1)", "abs((1)`)", "1"); testOutput("abs(-1)", "abs((1)`)", "1");
testOutput("abs(1)", "abs(1)", "1"); testOutput("abs(1)", "abs(1)", "1");
} }
@Test @Test
public void testLn(){ public void testLn() {
testEvalError("ln(-1)", "ln((1)`)"); testEvalError("ln(-1)", "ln((1)`)");
testOutput("ln2", "ln(2)", "0.6931471805599453094172321214581765680755"); testOutput("ln2", "ln(2)", "0.6931471805599453094172321214581765680755");
} }
@Test @Test
public void testSqrt(){ public void testSqrt() {
testOutput("sqrt0", "sqrt(0)", "0"); testOutput("sqrt0", "sqrt(0)", "0");
testOutput("sqrt4", "sqrt(4)", "2"); testOutput("sqrt4", "sqrt(4)", "2");
testOutput("sqrt2", "sqrt(2)", "1.4142135623730950488016887242096980785696"); testOutput("sqrt2", "sqrt(2)", "1.4142135623730950488016887242096980785696");
} }
@Test @Test
public void testExp(){ public void testExp() {
testOutput("exp0", "exp(0)", "1"); testOutput("exp0", "exp(0)", "1");
testOutput("exp1", "exp(1)", "2.718281828459045235360287471352662497757247"); testOutput("exp1", "exp(1)", "2.718281828459045235360287471352662497757247");
testOutput("exp300", "exp(300)", "1.9424263952412559365842088360176992193662086"); testOutput("exp300", "exp(300)", "1.9424263952412559365842088360176992193662086");
@@ -93,7 +93,7 @@ public class CalculationTests {
} }
@Test @Test
public void testPow(){ public void testPow() {
testOutput("0^2", "(0^2)", "0"); testOutput("0^2", "(0^2)", "0");
testOutput("2^0", "(2^0)", "1"); testOutput("2^0", "(2^0)", "1");
testOutput("2^1", "(2^1)", "2"); testOutput("2^1", "(2^1)", "2");
@@ -101,7 +101,7 @@ public class CalculationTests {
testOutput("2^50", "(2^50)", "112589990684262"); testOutput("2^50", "(2^50)", "112589990684262");
testOutput("7^(-sqrt2*17)", "(7^((sqrt(2)*17))`)", "4.81354609155297814551845300063563"); testOutput("7^(-sqrt2*17)", "(7^((sqrt(2)*17))`)", "4.81354609155297814551845300063563");
testEvalError("0^0", "(0^0)"); testEvalError("0^0", "(0^0)");
testEvalError("(-13)^.9999", "((13)`^0.9999)"); testEvalError("(-13)^.9999", "((13)`^.9999)");
} }
} }

7
docs/404.html Normal file
View File

@@ -0,0 +1,7 @@
---
layout: base
---
<h1>404</h1>
<p><strong>Page not found :(</strong></p>
<p>The requested page could not be found.</p>

27
docs/Gemfile Normal file
View File

@@ -0,0 +1,27 @@
source "https://rubygems.org"
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
#
# bundle exec jekyll serve
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
gem "jekyll", "3.5.2"
# This is the default theme for new Jekyll sites. You may change this to anything you like.
gem "minima", "~> 2.0"
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
# gem "github-pages", group: :jekyll_plugins
# If you have any plugins, put them here!
group :jekyll_plugins do
gem "jekyll-feed", "~> 0.6"
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

58
docs/Gemfile.lock Normal file
View File

@@ -0,0 +1,58 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.5.1)
public_suffix (~> 2.0, >= 2.0.2)
colorator (1.1.0)
ffi (1.9.18)
forwardable-extended (2.6.0)
jekyll (3.5.2)
addressable (~> 2.4)
colorator (~> 1.0)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 1.1)
kramdown (~> 1.3)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (~> 1.7)
safe_yaml (~> 1.0)
jekyll-feed (0.9.2)
jekyll (~> 3.3)
jekyll-sass-converter (1.5.0)
sass (~> 3.4)
jekyll-watch (1.5.0)
listen (~> 3.0, < 3.1)
kramdown (1.14.0)
liquid (4.0.0)
listen (3.0.8)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
mercenary (0.3.6)
minima (2.1.1)
jekyll (~> 3.3)
pathutil (0.14.0)
forwardable-extended (~> 2.6)
public_suffix (2.0.5)
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
rouge (1.11.1)
safe_yaml (1.0.4)
sass (3.5.1)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
PLATFORMS
ruby
DEPENDENCIES
jekyll (= 3.5.2)
jekyll-feed (~> 0.6)
minima (~> 2.0)
tzinfo-data
BUNDLED WITH
1.15.3

43
docs/_config.yml Normal file
View File

@@ -0,0 +1,43 @@
# Welcome to Jekyll!
#
# This config file is meant for settings that affect your whole blog, values
# which you are expected to set up once and rarely edit after that. If you find
# yourself editing this file very often, consider using Jekyll's data files
# feature for the data you need to update frequently.
#
# For technical reasons, this file is *NOT* reloaded automatically when you use
# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
# Site settings
# These are used to personalize your new site. If you look in the HTML files,
# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
# You can create any custom variable you would like, and they will be accessible
# in the templates via {{ site.myvariable }}.
title: Abacus
email: danila.fedorin@gmail.com
description: > # this means to ignore newlines until "baseurl:"
This is the home page of Abacus,
a calculator developed during
the summer of 2017 as a tool
for the more tech-savvy users.
baseurl: "/abacus" # the subpath of your site, e.g. /blog
url: "htts://danilafe.github.io" # the base hostname & protocol for your site, e.g. http://example.com
github_username: DanilaFe
include: ['_pages']
# Build settings
markdown: kramdown
plugins:
- jekyll-feed
# Exclude from processing.
# The following items will not be processed, by default. Create a custom list
# to override the default setting.
# exclude:
# - Gemfile
# - Gemfile.lock
# - node_modules
# - vendor/bundle/
# - vendor/cache/
# - vendor/gems/
# - vendor/ruby/

View File

17
docs/_includes/head.html Normal file
View File

@@ -0,0 +1,17 @@
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% if page.title %}{{ page.title | escape }}{% else %}{{ site.title | escape }}{% endif %}</title>
<meta name="description" content="{{ page.excerpt | default: site.description | strip_html | normalize_whitespace | truncate: 160 | escape }}">
<link rel="stylesheet" href="{{ "assets/css/main.css" | relative_url }}">
<link rel="canonical" href="{{ page.url | replace:'index.html','' | absolute_url }}">
<link rel="alternate" type="application/rss+xml" title="{{ site.title | escape }}" href="{{ "/feed.xml" | relative_url }}">
{% if jekyll.environment == 'production' and site.google_analytics %}
{% include google-analytics.html %}
{% endif %}
</head>

View File

@@ -0,0 +1,10 @@
<nav>
<div class="center">
<a href="{{ "/" | relative_url }}" class="primary-link">{{ site.title }}</a>
{% for page in site.pages %}
{% if page.in_header %}
<a href="{{ page.url | relative_url }}">{{ page.title }}</a>
{% endif %}
{% endfor %}
</div>
</nav>

17
docs/_layouts/base.html Normal file
View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
{% include head.html %}
<body>
{% include header.html %}
<div class="content center">
{{ content }}
</div>
{% include footer.html %}
</body>
</html>

46
docs/_layouts/home.html Normal file
View File

@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
{% include head.html %}
<style>
body {
margin-top: 100px;
color: white;
text-align: center;
}
h1, h2, h3, h4, h5, h6 {
font-family: "Source Code Pro"
}
img {
margin: auto;
width: 100%;
max-width: 432px;
}
div#buttons {
margin-top: 40px;
margin-bottom: 40px;
}
a {
background-color: white;
color: #06e8a4;
}
a:hover {
background-color: #06e8a4;
color: white;
}
</style>
<body>
<h1>Abacus</h1>
<h2>The programmer's calculator</h2>
<div id="buttons">
<a class="button inverted" href="{{ "/download" | relative_url }}">Download</a>
<a class="button inverted" href="{{ "/about" | relative_url }}">About</a>
<a class="button inverted" href="https://github.com/DanilaFe/abacus">Contribute</a>
<a class="button inverted" href="https://github.com/DanilaFe/abacus/wiki">Wiki</a>
</div>
<img src="http://i.imgur.com/Min70QY.png" title="source: imgur.com" />
</body>
</html>

5
docs/_layouts/page.html Normal file
View File

@@ -0,0 +1,5 @@
---
layout: base
---
<h1>{{ page.title }}</h1>
{{ content }}

27
docs/_pages/about.md Normal file
View File

@@ -0,0 +1,27 @@
---
in_header: true
layout: page
title: About
permalink: /about/
---
## So... what IS Abacus?
It's a calculator. Obviously. But what makes it better than
what already exists? There's a few things. Abacus is:
* Programmable, and not in TI Basic.
* Precise. With the "precise" option, Abacus can keep up to 50 significant figures.
* Capable. Ever wonder what 2<sup>700</sup> is? How about 8!!? Abacus can tell you!
* Offline. While Wolfram Alpha can do powerful math, it needs internet connection!
* Built for the desktop. Why use buttons on the screen when there's buttons on the keyboard?
* Open source. Don't like something? Help is always welcome!
## Why was Abacus made?
The initial project was proposed for the [Northwest Advanced Programming Workshop](http://nwapw.org/about/).
You can read the project proposal on the main GitHub page, although the idea has
changed quite a bit, mostly in shifting from "fast" to "precise".
## What is Abacus made with?
Java and Kotlin. Java provides a good layer of abstraction and a great standard
library, while Kotlin allows for the reduction of boilerplate code and null
safety. Using JVM-based languages also allows Abacus to expose its entire
API to plugins, and load them at runtime.

34
docs/_pages/download.md Normal file
View File

@@ -0,0 +1,34 @@
---
in_header: true
layout: page
title: Download
permalink: /download/
---
Currently, we do not provide standalone executables due to our unfamiliarity with
including 3rd-party software. Abacus uses a number of open source libraries,
and we do not want to breach the license terms for any of them. As soon as
as we figure out the correct way to distribute Abacus, we will make a
standalone distribution available. In the meantime, please use the below
steps to run Abacus from source.
## Getting the Code
Abacus is an open source project, and is distributed under the MIT license.
If you would like to download the source code, simply clone it from
[GitHub](https://github.com/DanilaFe/abacus).
Alternatively, if you don't want the bleeding edge version, check out the
[releases](https://github.com/DanilaFe/abacus/releases).
## Running from Source
Once you have unpacked the source code, you can simply run it from
the command line via the shell command:
```
./gradlew run
```
If you're on Windows, the command is similar:
```
gradlew run
```
This should download a distribution of Gradle, a build system that is
used to compile Abacus. After some time, the Abacus window should appear.
From there, you can use it normally.

119
docs/assets/css/main.scss Normal file
View File

@@ -0,0 +1,119 @@
---
---
@import url('https://fonts.googleapis.com/css?family=Source+Code+Pro|Open+Sans|Raleway');
$background-color: #19d69e;
$code-color: #efefef;
$accent-color: #00AFE8;
$clear-color: white;
$title-font: "Open Sans";
$text-font: Helvetica;
$code-font: "Source Code Pro";
$max-width: 850px;
a {
text-decoration: none;
color: $background-color;
&.button {
display: inline-block;
background-color: $background-color;
color: $clear-color;
padding: 10px;
text-decoration: none;
border-radius: 2px;
margin: 10px;
transition: background-color .25s;
&:hover {
background-color: $clear-color;
color: $background-color;
}
&.inverted {
background-color: $clear-color;
color: $background-color;
&:hover {
background-color: $background-color;
color: $clear-color;
}
}
}
}
h1, h2, h3, h4, h5, h6 {
font: {
family: $title-font;
}
}
h1 {
font-size: 50px;
}
nav {
box-sizing: border-box;
background-color: $clear-color;
width: 100%;
padding: 20px;
a {
text-decoration: none;
color: $background-color;
font-size: 20px;
margin-right: 10px;
&.primary-link {
font-size: 30px;
margin-right: 20px;
}
&:hover {
color: $accent-color;
}
transition: color .25s;
}
}
body {
background-color: $background-color;
font: {
family: $text-font;
}
margin: 0px;
}
.center {
box-sizing: border-box;
width: 100%;
max-width: $max-width;
@media (min-width: $max-width) {
margin: {
left: auto;
right: auto;
}
}
}
.content {
margin-top: 20px;
padding: 30px;
background-color: $clear-color;
}
code {
background-color: $code-color;
display: inline-block;
padding: 5px;
font-family: $code-font;
pre & {
padding: 10px;
display: block;
width: 100%;
}
}

6
docs/index.md Normal file
View File

@@ -0,0 +1,6 @@
---
# You don't need to edit this file, it's empty on purpose.
# Edit theme's home layout instead if you wanna make some changes
# See: https://jekyllrb.com/docs/themes/#overriding-theme-defaults
layout: home
---

View File

@@ -1,10 +1,7 @@
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.1.3'
}
apply plugin: 'application' apply plugin: 'application'
dependencies { dependencies {
compile project(':core') compile project(':core')
} }
mainClassName = 'org.nwapw.abacus.fx.AbacusApplication' mainClassName = 'org.nwapw.abacus.fx.AbacusApplication'

View File

@@ -17,6 +17,10 @@ public class AbacusApplication extends Application {
*/ */
private AbacusController controller; private AbacusController controller;
public static void main(String[] args) {
launch(args);
}
@Override @Override
public void start(Stage primaryStage) throws Exception { public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/abacus.fxml")); FXMLLoader loader = new FXMLLoader(getClass().getResource("/abacus.fxml"));
@@ -34,8 +38,4 @@ public class AbacusApplication extends Application {
controller.performStop(); controller.performStop();
} }
public static void main(String[] args){
launch(args);
}
} }

View File

@@ -1,13 +1,10 @@
package org.nwapw.abacus.fx; package org.nwapw.abacus.fx;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList; import javafx.collections.transformation.FilteredList;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.*; import javafx.scene.control.*;
import javafx.scene.control.cell.CheckBoxListCell; import javafx.scene.control.cell.CheckBoxListCell;
import javafx.scene.text.Text; import javafx.scene.text.Text;
@@ -136,36 +133,12 @@ public class AbacusController implements PluginListener {
* The abacus instance used for changing the plugin configuration. * The abacus instance used for changing the plugin configuration.
*/ */
private Abacus abacus; private Abacus abacus;
/**
* Boolean which represents whether changes were made to the configuration.
*/
private boolean changesMade;
/**
* Whether an alert about changes to the configuration was already shown.
*/
private boolean reloadAlertShown;
/**
* The alert shown when a press to "apply" is needed.
*/
private Alert reloadAlert;
/**
* The runnable that takes care of killing computations that take too long.
*/
private final Runnable TIMER_RUNNABLE = () -> {
try {
Configuration abacusConfig = abacus.getConfiguration();
if(abacusConfig.getComputationDelay() == 0) return;
Thread.sleep((long) (abacusConfig.getComputationDelay() * 1000));
performStop();
} catch (InterruptedException e) { }
};
/** /**
* The runnable used to perform the calculation. * The runnable used to perform the calculation.
*/ */
private final Runnable CALCULATION_RUNNABLE = new Runnable() { private final Runnable CALCULATION_RUNNABLE = new Runnable() {
private String attemptCalculation(){ private String attemptCalculation() {
try { try {
TreeNode constructedTree = abacus.parseString(inputField.getText()); TreeNode constructedTree = abacus.parseString(inputField.getText());
if (constructedTree == null) { if (constructedTree == null) {
@@ -180,7 +153,7 @@ public class AbacusController implements PluginListener {
return resultingString; return resultingString;
} catch (ComputationInterruptedException exception) { } catch (ComputationInterruptedException exception) {
return ERR_STOP; return ERR_STOP;
} catch (RuntimeException exception){ } catch (RuntimeException exception) {
exception.printStackTrace(); exception.printStackTrace();
return ERR_EXCEPTION; return ERR_EXCEPTION;
} }
@@ -197,6 +170,18 @@ public class AbacusController implements PluginListener {
}); });
} }
}; };
/**
* Boolean which represents whether changes were made to the configuration.
*/
private boolean changesMade;
/**
* Whether an alert about changes to the configuration was already shown.
*/
private boolean reloadAlertShown;
/**
* The alert shown when a press to "apply" is needed.
*/
private Alert reloadAlert;
/** /**
* The thread that is waiting to pause the calculation. * The thread that is waiting to pause the calculation.
*/ */
@@ -205,6 +190,18 @@ public class AbacusController implements PluginListener {
* The thread in which the computation runs. * The thread in which the computation runs.
*/ */
private Thread calculationThread; private Thread calculationThread;
/**
* The runnable that takes care of killing computations that take too long.
*/
private final Runnable TIMER_RUNNABLE = () -> {
try {
Configuration abacusConfig = abacus.getConfiguration();
if (abacusConfig.getComputationDelay() == 0) return;
Thread.sleep((long) (abacusConfig.getComputationDelay() * 1000));
performStop();
} catch (InterruptedException e) {
}
};
/** /**
* Alerts the user if the changes they made * Alerts the user if the changes they made
@@ -265,7 +262,7 @@ public class AbacusController implements PluginListener {
computationLimitField.setText(Double.toString(abacus.getConfiguration().getComputationDelay())); computationLimitField.setText(Double.toString(abacus.getConfiguration().getComputationDelay()));
computationLimitField.textProperty().addListener((observable, oldValue, newValue) -> { computationLimitField.textProperty().addListener((observable, oldValue, newValue) -> {
if(!newValue.matches("(\\d+(\\.\\d*)?)?")) { if (!newValue.matches("(\\d+(\\.\\d*)?)?")) {
computationLimitField.setText(oldValue); computationLimitField.setText(oldValue);
} else { } else {
changesMade = true; changesMade = true;
@@ -292,12 +289,12 @@ public class AbacusController implements PluginListener {
} }
@FXML @FXML
public void performStop(){ public void performStop() {
if(calculationThread != null) { if (calculationThread != null) {
calculationThread.interrupt(); calculationThread.interrupt();
calculationThread = null; calculationThread = null;
} }
if(computationLimitThread != null){ if (computationLimitThread != null) {
computationLimitThread.interrupt(); computationLimitThread.interrupt();
computationLimitThread = null; computationLimitThread = null;
} }
@@ -312,7 +309,7 @@ public class AbacusController implements PluginListener {
} }
@FXML @FXML
public void performScan(){ public void performScan() {
PluginManager abacusPluginManager = abacus.getPluginManager(); PluginManager abacusPluginManager = abacus.getPluginManager();
abacusPluginManager.removeAll(); abacusPluginManager.removeAll();
abacusPluginManager.addInstantiated(new StandardPlugin(abacus.getPluginManager())); abacusPluginManager.addInstantiated(new StandardPlugin(abacus.getPluginManager()));
@@ -339,7 +336,7 @@ public class AbacusController implements PluginListener {
for (ToggleablePlugin pluginEntry : enabledPlugins) { for (ToggleablePlugin pluginEntry : enabledPlugins) {
if (!pluginEntry.isEnabled()) disabledPlugins.add(pluginEntry.getClassName()); if (!pluginEntry.isEnabled()) disabledPlugins.add(pluginEntry.getClassName());
} }
if(computationLimitField.getText().matches("\\d*(\\.\\d+)?") && computationLimitField.getText().length() != 0) if (computationLimitField.getText().matches("\\d*(\\.\\d+)?") && computationLimitField.getText().length() != 0)
configuration.setComputationDelay(Double.parseDouble(computationLimitField.getText())); configuration.setComputationDelay(Double.parseDouble(computationLimitField.getText()));
configuration.saveTo(CONFIG_FILE); configuration.saveTo(CONFIG_FILE);
changesMade = false; changesMade = false;

View File

@@ -14,7 +14,7 @@ public class DocumentationCell extends ListCell<Documentation> {
private Label longDescription; private Label longDescription;
private TitledPane titledPane; private TitledPane titledPane;
public DocumentationCell(){ public DocumentationCell() {
VBox vbox = new VBox(); VBox vbox = new VBox();
vbox.setSpacing(10); vbox.setSpacing(10);
titledPane = new TitledPane(); titledPane = new TitledPane();
@@ -41,7 +41,7 @@ public class DocumentationCell extends ListCell<Documentation> {
@Override @Override
protected void updateItem(Documentation item, boolean empty) { protected void updateItem(Documentation item, boolean empty) {
super.updateItem(item, empty); super.updateItem(item, empty);
if(empty){ if (empty) {
codeNameLabel.setText(""); codeNameLabel.setText("");
nameLabel.setText(""); nameLabel.setText("");
description.setText(""); description.setText("");

View File

@@ -14,7 +14,7 @@ import javafx.beans.property.SimpleStringProperty
* @param parsed the parsed version of the input. * @param parsed the parsed version of the input.
* @param output the output string. * @param output the output string.
*/ */
class HistoryModel(input: String, parsed: String, output: String){ class HistoryModel(input: String, parsed: String, output: String) {
/** /**
* The property that holds the input. * The property that holds the input.

View File

@@ -12,7 +12,7 @@ import javafx.beans.property.SimpleBooleanProperty
* @param className the name of the class that this model concerns. * @param className the name of the class that this model concerns.
* @param enabled whether or not the model should start enabled. * @param enabled whether or not the model should start enabled.
*/ */
class ToggleablePlugin (val className: String, enabled: Boolean) { class ToggleablePlugin(val className: String, enabled: Boolean) {
/** /**
* The property used to interact with JavaFX components. * The property used to interact with JavaFX components.