mirror of
https://github.com/DanilaFe/abacus
synced 2024-12-22 07:20:09 -08:00
Merge branch 'master' into context
This commit is contained in:
commit
1667edc72b
|
@ -1,4 +1,3 @@
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'com.moandjiezana.toml:toml4j:0.7.1'
|
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,159 +0,0 @@
|
||||||
package org.nwapw.abacus.config;
|
|
||||||
|
|
||||||
import com.moandjiezana.toml.Toml;
|
|
||||||
import com.moandjiezana.toml.TomlWriter;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The configuration object that stores
|
|
||||||
* options that the user can change.
|
|
||||||
*/
|
|
||||||
public class Configuration {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The defaults TOML string.
|
|
||||||
*/
|
|
||||||
private static final String DEFAULT_CONFIG =
|
|
||||||
"numberImplementation = \"naive\"\n" +
|
|
||||||
"disabledPlugins = []";
|
|
||||||
/**
|
|
||||||
* The defaults TOML object, parsed from the string.
|
|
||||||
*/
|
|
||||||
private static final Toml DEFAULT_TOML = new Toml().read(DEFAULT_CONFIG);
|
|
||||||
/**
|
|
||||||
* The TOML writer used to write this configuration to a file.
|
|
||||||
*/
|
|
||||||
private static final TomlWriter TOML_WRITER = new TomlWriter();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The computation delay for which the thread can run without interruption.
|
|
||||||
*/
|
|
||||||
private double computationDelay = 0;
|
|
||||||
/**
|
|
||||||
* The implementation of the number that should be used.
|
|
||||||
*/
|
|
||||||
private String numberImplementation = "<default>";
|
|
||||||
/**
|
|
||||||
* The list of disabled plugins in this Configuration.
|
|
||||||
*/
|
|
||||||
private Set<String> disabledPlugins = new HashSet<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new configuration form the given configuration.
|
|
||||||
*
|
|
||||||
* @param copyFrom the configuration to copy.
|
|
||||||
*/
|
|
||||||
public Configuration(Configuration copyFrom) {
|
|
||||||
copyFrom(copyFrom);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new configuration with the given values.
|
|
||||||
*
|
|
||||||
* @param computationDelay the delay before the computation gets killed.
|
|
||||||
* @param numberImplementation the number implementation, like "naive" or "precise"
|
|
||||||
* @param disabledPlugins the list of disabled plugins.
|
|
||||||
*/
|
|
||||||
public Configuration(double computationDelay, String numberImplementation, String[] disabledPlugins) {
|
|
||||||
this.computationDelay = computationDelay;
|
|
||||||
this.numberImplementation = numberImplementation;
|
|
||||||
this.disabledPlugins.addAll(Arrays.asList(disabledPlugins));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a configuration from a given file, keeping non-specified fields default.
|
|
||||||
*
|
|
||||||
* @param fromFile the file to load from.
|
|
||||||
*/
|
|
||||||
public Configuration(File fromFile) {
|
|
||||||
if (!fromFile.exists()) return;
|
|
||||||
copyFrom(new Toml(DEFAULT_TOML).read(fromFile).to(Configuration.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copies the values from the given configuration into this one.
|
|
||||||
*
|
|
||||||
* @param otherConfiguration the configuration to copy from.
|
|
||||||
*/
|
|
||||||
public void copyFrom(Configuration otherConfiguration) {
|
|
||||||
this.computationDelay = otherConfiguration.computationDelay;
|
|
||||||
this.numberImplementation = otherConfiguration.numberImplementation;
|
|
||||||
this.disabledPlugins.addAll(otherConfiguration.disabledPlugins);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves this configuration to the given file, creating
|
|
||||||
* any directories that do not exist.
|
|
||||||
*
|
|
||||||
* @param file the file to save to.
|
|
||||||
*/
|
|
||||||
public void saveTo(File file) {
|
|
||||||
if (file.getParentFile() != null) file.getParentFile().mkdirs();
|
|
||||||
try {
|
|
||||||
TOML_WRITER.write(this, file);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of this configuration as a string.
|
|
||||||
*
|
|
||||||
* @return the string that represents this configuration.
|
|
||||||
*/
|
|
||||||
public String asTomlString() {
|
|
||||||
return TOML_WRITER.write(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the number implementation from this configuration.
|
|
||||||
*
|
|
||||||
* @return the number implementation.
|
|
||||||
*/
|
|
||||||
public String getNumberImplementation() {
|
|
||||||
return numberImplementation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the number implementation for the configuration
|
|
||||||
*
|
|
||||||
* @param numberImplementation the number implementation.
|
|
||||||
*/
|
|
||||||
public void setNumberImplementation(String numberImplementation) {
|
|
||||||
this.numberImplementation = numberImplementation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the list of disabled plugins.
|
|
||||||
*
|
|
||||||
* @return the list of disabled plugins.
|
|
||||||
*/
|
|
||||||
public Set<String> getDisabledPlugins() {
|
|
||||||
return disabledPlugins;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the computation delay specified in the configuration.
|
|
||||||
*
|
|
||||||
* @return the computaton delay.
|
|
||||||
*/
|
|
||||||
public double getComputationDelay() {
|
|
||||||
return computationDelay;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the computation delay.
|
|
||||||
*
|
|
||||||
* @param computationDelay the new computation delay.
|
|
||||||
*/
|
|
||||||
public void setComputationDelay(double computationDelay) {
|
|
||||||
this.computationDelay = computationDelay;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package org.nwapw.abacus.config
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class that holds information that tells Abacus how to behave.
|
||||||
|
*
|
||||||
|
* Configuration stores information about how Abacus should behave, for
|
||||||
|
* instance, what number implementation it should use and what
|
||||||
|
* plugins should be ignored during loading.
|
||||||
|
*
|
||||||
|
* @property numberImplementation the number implementation Abacus should use for loading.
|
||||||
|
* @param disabledPlugins the plugins that should be disabled and not loaded by the plugin manager.
|
||||||
|
*/
|
||||||
|
open class Configuration(var numberImplementation: String = "<default>", disabledPlugins: Array<String> = emptyArray()) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The set of disabled plugins that should be ignored by the plugin manager.
|
||||||
|
*/
|
||||||
|
val disabledPlugins = disabledPlugins.toMutableSet()
|
||||||
|
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ import org.nwapw.abacus.tree.TreeNode;
|
||||||
|
|
||||||
public class CalculationTests {
|
public class CalculationTests {
|
||||||
|
|
||||||
private static Abacus abacus = new Abacus(new Configuration(0, "precise", new String[]{}));
|
private static Abacus abacus = new Abacus(new Configuration( "precise", new String[]{}));
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void prepareTests() {
|
public static void prepareTests() {
|
||||||
|
|
|
@ -17,7 +17,7 @@ import java.util.List;
|
||||||
|
|
||||||
public class TokenizerTests {
|
public class TokenizerTests {
|
||||||
|
|
||||||
private static Abacus abacus = new Abacus(new Configuration(0, "precise", new String[]{}));
|
private static Abacus abacus = new Abacus(new Configuration("precise", new String[]{}));
|
||||||
private static LexerTokenizer lexerTokenizer = new LexerTokenizer();
|
private static LexerTokenizer lexerTokenizer = new LexerTokenizer();
|
||||||
private static NumberFunction subtractFunction = new NumberFunction() {
|
private static NumberFunction subtractFunction = new NumberFunction() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
{% include head.html %}
|
{% include head.html %}
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
|
margin: 0px;
|
||||||
margin-top: 50px;
|
margin-top: 50px;
|
||||||
color: white;
|
color: white;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -37,6 +38,58 @@
|
||||||
background-color: #06e8a4;
|
background-color: #06e8a4;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.fullwidth {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.fullwidth img {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 450px;
|
||||||
|
margin: auto;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
display: block;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.white {
|
||||||
|
background-color: white;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.green {
|
||||||
|
background-color: #06e8a4;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.fullwidth div.double {
|
||||||
|
height: 100%;
|
||||||
|
text-align: left;
|
||||||
|
width: 50%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 40px;
|
||||||
|
float: left;
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 750px) {
|
||||||
|
div.fullwidth div.double {
|
||||||
|
width: 100%;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
div.fullwidth img {
|
||||||
|
margin-top: 0px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div.fullwidth div.double h1, h2, h3, h4, h5, h6 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
<body>
|
<body>
|
||||||
<img src="https://raw.githubusercontent.com/DanilaFe/abacus/master/image/logo.png" id="logo">
|
<img src="https://raw.githubusercontent.com/DanilaFe/abacus/master/image/logo.png" id="logo">
|
||||||
|
@ -49,5 +102,58 @@
|
||||||
<a class="button inverted" href="https://github.com/DanilaFe/abacus/wiki">Wiki</a>
|
<a class="button inverted" href="https://github.com/DanilaFe/abacus/wiki">Wiki</a>
|
||||||
</div>
|
</div>
|
||||||
<img src="http://i.imgur.com/Min70QY.png" title="source: imgur.com" id="image_preview"/>
|
<img src="http://i.imgur.com/Min70QY.png" title="source: imgur.com" id="image_preview"/>
|
||||||
|
<h2>Features</h2>
|
||||||
|
<div class="fullwidth white">
|
||||||
|
<div class="double">
|
||||||
|
<img src="https://i.imgur.com/gmGJBBK.png">
|
||||||
|
</div>
|
||||||
|
<div class="double">
|
||||||
|
<h2>Precision</h2>
|
||||||
|
Abacus uses a mathematical tool called Taylor Series to determine values
|
||||||
|
as accurate as the user desires. Of course, this comes with some
|
||||||
|
performance issues with larger numbers. However, Abacus has been
|
||||||
|
tested to generate the value of e correctly to a thousand digits.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="fullwidth green">
|
||||||
|
<div class="double">
|
||||||
|
<h2>Configurable and Customizable</h2>
|
||||||
|
The very first idea for Abacus was inspired by how difficult it was
|
||||||
|
to program a TI-84 calculator. Only two languages were available, TI-BASIC
|
||||||
|
and Assembly, the latter having virtually no documentation. Determined
|
||||||
|
to be better than a TI-84, Abacus implemented a plugin system that allows
|
||||||
|
users to easily create and add plugins written in the same programming
|
||||||
|
language as Abacus itself - Java. These plugins can access the full
|
||||||
|
power of the language, and implement their own ways of handling numbers,
|
||||||
|
as well as their own functions and even operators.<br><br>
|
||||||
|
Besides the ability to add plugins, Abacus also adds some general
|
||||||
|
options that can be used to make the user's experience more pleasant.
|
||||||
|
For instance, it allows for a computation limit to be set in order
|
||||||
|
to prevent excessively long evaluation: 8!!! is, for example, an expression
|
||||||
|
that even Wolfram Alpha doesn't compute accurately, and will never finish
|
||||||
|
on Abacus (it's simply too large). The computation limit will allow Abacus
|
||||||
|
to kill a computation if it takes too long. Support for user-definable
|
||||||
|
precision is also planned.
|
||||||
|
</div>
|
||||||
|
<div class="double">
|
||||||
|
<img src="https://i.imgur.com/JzenWPV.png">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="fullwidth white">
|
||||||
|
<div class="double">
|
||||||
|
<img src="https://i.imgur.com/jY17I3A.png">
|
||||||
|
</div>
|
||||||
|
<div class="double">
|
||||||
|
<h2>Built-in Documentation</h2>
|
||||||
|
Abacus plugins are given a mechanism to register documentation for
|
||||||
|
the functions that they provide. The Abacus GUI displays these
|
||||||
|
functions in a searchable list, allowing the user to read the parameters
|
||||||
|
that have to be supplied to each function, as well as learn about
|
||||||
|
its return value.<br><br>
|
||||||
|
The search finds functions not only by their names, but also by relevant
|
||||||
|
terms mentioned in the function's description, thus allowing related
|
||||||
|
functions to be displayed together.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -7,7 +7,7 @@ $code-color: #efefef;
|
||||||
$accent-color: #00AFE8;
|
$accent-color: #00AFE8;
|
||||||
$clear-color: white;
|
$clear-color: white;
|
||||||
$title-font: "Open Sans";
|
$title-font: "Open Sans";
|
||||||
$text-font: Helvetica;
|
$text-font: "Raleway";
|
||||||
$code-font: "Source Code Pro";
|
$code-font: "Source Code Pro";
|
||||||
$max-width: 850px;
|
$max-width: 850px;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
apply plugin: 'application'
|
apply plugin: 'application'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
compile 'com.moandjiezana.toml:toml4j:0.7.1'
|
||||||
compile project(':core')
|
compile project(':core')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,7 @@ public class AbacusController implements PluginListener {
|
||||||
*/
|
*/
|
||||||
private final Runnable TIMER_RUNNABLE = () -> {
|
private final Runnable TIMER_RUNNABLE = () -> {
|
||||||
try {
|
try {
|
||||||
Configuration abacusConfig = abacus.getConfiguration();
|
ExtendedConfiguration abacusConfig = (ExtendedConfiguration) abacus.getConfiguration();
|
||||||
if (abacusConfig.getComputationDelay() == 0) return;
|
if (abacusConfig.getComputationDelay() == 0) return;
|
||||||
Thread.sleep((long) (abacusConfig.getComputationDelay() * 1000));
|
Thread.sleep((long) (abacusConfig.getComputationDelay() * 1000));
|
||||||
performStop();
|
performStop();
|
||||||
|
@ -260,12 +260,12 @@ public class AbacusController implements PluginListener {
|
||||||
if (oldValue.equals(settingsTab)) alertIfApplyNeeded(true);
|
if (oldValue.equals(settingsTab)) alertIfApplyNeeded(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
abacus = new Abacus(new Configuration(CONFIG_FILE));
|
abacus = new Abacus(new ExtendedConfiguration(CONFIG_FILE));
|
||||||
PluginManager abacusPluginManager = abacus.getPluginManager();
|
PluginManager abacusPluginManager = abacus.getPluginManager();
|
||||||
abacusPluginManager.addListener(this);
|
abacusPluginManager.addListener(this);
|
||||||
performScan();
|
performScan();
|
||||||
|
|
||||||
computationLimitField.setText(Double.toString(abacus.getConfiguration().getComputationDelay()));
|
computationLimitField.setText(Double.toString(((ExtendedConfiguration) 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);
|
||||||
|
@ -342,8 +342,8 @@ public class AbacusController implements PluginListener {
|
||||||
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()));
|
((ExtendedConfiguration) configuration).setComputationDelay(Double.parseDouble(computationLimitField.getText()));
|
||||||
configuration.saveTo(CONFIG_FILE);
|
((ExtendedConfiguration) configuration).saveTo(CONFIG_FILE);
|
||||||
changesMade = false;
|
changesMade = false;
|
||||||
reloadAlertShown = false;
|
reloadAlertShown = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
package org.nwapw.abacus.fx
|
||||||
|
|
||||||
|
import com.moandjiezana.toml.Toml
|
||||||
|
import com.moandjiezana.toml.TomlWriter
|
||||||
|
import org.nwapw.abacus.config.Configuration
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional settings for user interface.
|
||||||
|
*
|
||||||
|
* ExtendedConfiguration is used to add other settings
|
||||||
|
* that aren't built into Abacus core, but are necessary
|
||||||
|
* for the fx module.
|
||||||
|
*
|
||||||
|
* @property computationDelay the delay before which the computation stops.
|
||||||
|
* @param implementation the number implementation, same as [Configuration.numberImplementation]
|
||||||
|
* @param disabledPlugins the list of plugins that should be disabled, same as [Configuration.disabledPlugins]
|
||||||
|
*/
|
||||||
|
class ExtendedConfiguration(var computationDelay: Double = 0.0,
|
||||||
|
implementation: String = "<default>",
|
||||||
|
disabledPlugins: Array<String> = emptyArray())
|
||||||
|
: Configuration(implementation, disabledPlugins) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* The default TOML.
|
||||||
|
*/
|
||||||
|
val DEFAULT_TOML_STRING = """
|
||||||
|
computationDelay=0.0
|
||||||
|
implementation="naive"
|
||||||
|
disabledPlugins=[]
|
||||||
|
"""
|
||||||
|
/**
|
||||||
|
* A reader with the default TOML data.
|
||||||
|
*/
|
||||||
|
val DEFAULT_TOML_READER = Toml().read(DEFAULT_TOML_STRING)
|
||||||
|
/**
|
||||||
|
* A writer used to writing the configuration to disk.
|
||||||
|
*/
|
||||||
|
val DEFAULT_TOML_WRITER = TomlWriter()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new configuration from a file on disk.
|
||||||
|
* @param tomlFile the file from disk to load.
|
||||||
|
*/
|
||||||
|
constructor(tomlFile: File) : this() {
|
||||||
|
copyFrom(Toml(DEFAULT_TOML_READER).read(tomlFile).to(ExtendedConfiguration::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies data from another configuration into this one.
|
||||||
|
* @param config the configuration to copy from.
|
||||||
|
*/
|
||||||
|
fun copyFrom(config: ExtendedConfiguration) {
|
||||||
|
computationDelay = config.computationDelay
|
||||||
|
numberImplementation = config.numberImplementation
|
||||||
|
disabledPlugins.clear()
|
||||||
|
disabledPlugins.addAll(config.disabledPlugins)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves this configuration to a file.
|
||||||
|
* @param file the file to save to.
|
||||||
|
*/
|
||||||
|
fun saveTo(file: File) {
|
||||||
|
DEFAULT_TOML_WRITER.write(this, file)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user