1
0
mirror of https://github.com/DanilaFe/abacus synced 2024-12-22 15:30:09 -08:00

Merge branch 'master' into context

This commit is contained in:
Danila Fedorin 2017-09-11 19:14:07 -07:00
commit 1667edc72b
10 changed files with 205 additions and 168 deletions

View File

@ -1,4 +1,3 @@
dependencies { dependencies {
compile 'com.moandjiezana.toml:toml4j:0.7.1'
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
} }

View File

@ -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;
}
}

View File

@ -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()
}

View File

@ -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() {

View File

@ -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

View File

@ -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>

View File

@ -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;

View File

@ -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')
} }

View File

@ -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;
} }

View File

@ -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)
}
}