Page MenuHomedesp's stash

Calculator.java
No OneTemporary

Calculator.java

package me.despawningbone.discordbot.command.info;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EmptyStackException;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import javax.imageio.ImageIO;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.math3.special.Gamma;
import org.json.JSONObject;
import org.json.JSONTokener;
import com.neovisionaries.ws.client.WebSocket;
import com.neovisionaries.ws.client.WebSocketAdapter;
import com.neovisionaries.ws.client.WebSocketException;
import com.neovisionaries.ws.client.WebSocketFactory;
import me.despawningbone.discordbot.command.Command;
import me.despawningbone.discordbot.command.CommandResult;
import me.despawningbone.discordbot.command.CommandResult.CommandResultType;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User;
import net.objecthunter.exp4j.Expression;
import net.objecthunter.exp4j.ExpressionBuilder;
import net.objecthunter.exp4j.function.Function;
import net.objecthunter.exp4j.operator.Operator;
public class Calculator extends Command {
public Calculator() {
this.alias = Arrays.asList("calc");
this.desc = "Do some calculations!";
this.usage = "[-w] <operation>";
this.remarks = Arrays.asList("This calculator is using exp4j.",
"You can get the built in operators and functions at:", "http://projects.congrace.de/exp4j/",
"`!` - factorials", "`logx(base, num)` - logarithm (base x)", "are supported too.",
"\nYou can also query [Wolfram Alpha](https://www.wolframalpha.com/) using the `-w` switch.");
this.examples = Arrays.asList("3*4-2", "4 * (sin(3 - 5)) + 5!", "log(e) + logx(10, 100)", " -w laurent series log(x) about x=0");
}
Function logb = new Function("logx", 2) {
@Override
public double apply(double... args) {
return Math.log(args[1]) / Math.log(args[0]);
}
};
Function digamma = new Function("digamma", 1) {
@Override
public double apply(double... args) {
return Gamma.digamma(args[0]);
}
};
Operator factorial = new Operator("!", 2, true, Operator.PRECEDENCE_POWER + 1) {
@Override
public double apply(double... args) {
final long arg = (long) args[0];
if ((double) arg != args[0]) {
throw new IllegalArgumentException("Operand for factorial has to be an integer");
}
if (arg < 0) {
throw new IllegalArgumentException("The operand of the factorial can not " + "be " + "less than zero");
}
double result = 1;
for (int i = 1; i <= arg; i++) {
result *= i;
}
return result;
}
};
@Override
public CommandResult execute(TextChannel channel, User author, Message msg, String[] args) {
List<String> params = new ArrayList<>(Arrays.asList(args));
if(params.removeAll(Collections.singleton("-w"))) {
return queryWolfram(String.join(" ", params), channel);
} else {
if (args.length < 1) {
return new CommandResult(CommandResultType.INVALIDARGS, "Please enter an operation.");
}
String splitted = String.join(" ", args);
if (msg.getContentDisplay().toLowerCase().contains("the meaning of life, the universe, and everything")) { // easter egg
channel.sendMessage("The answer is: `42`").queue();
return new CommandResult(CommandResultType.SUCCESS, "Executed easter egg");
}
if (splitted.equals("9+10") || splitted.equals("9 + 10")) { // easter egg
channel.sendMessage("The answer is: `21`\n\n *i am smart ;)*").queue();
return new CommandResult(CommandResultType.SUCCESS, "Executed easter egg");
}
if (splitted.equals("666") || splitted.equals("333")) { // easter egg
channel.sendMessage("No you don't").queue();
return new CommandResult(CommandResultType.SUCCESS, "Executed easter egg");
} else {
String operation = String.join("", args);
if (operation.contains("!")) {
int index = operation.indexOf("!");
while (index >= 0) { // indexOf returns -1 if no match found
operation = new StringBuilder(operation).insert(index + 1, "(1)").toString();
index = operation.indexOf("!", index + 1);
}
}
DecimalFormat format = new DecimalFormat();
format.setDecimalSeparatorAlwaysShown(false);
// System.out.println(operation);
Expression e = null;
String ans = null;
double planckConstant = 6.62607004 * Math.pow(10, -34);
double eulerMascheroni = 0.57721566490153286060651209008240243104215933593992;
try {
e = new ExpressionBuilder(operation).variable("h").variable("γ").function(digamma).function(logb).operator(factorial).build()
.setVariable("h", planckConstant).setVariable("γ", eulerMascheroni);
ans = Double.toString(e.evaluate());
// String ans = format.format(e.evaluate());
} catch (EmptyStackException e1) {
return new CommandResult(CommandResultType.INVALIDARGS, "You have imbalanced parentheses.");
} catch (ArithmeticException e1) {
return new CommandResult(CommandResultType.INVALIDARGS, "You cannot divide by zero.");
} catch (IllegalArgumentException e1) {
return new CommandResult(CommandResultType.FAILURE, "An error has occured: " + e1.getMessage());
}
if (ans.equals("NaN")) {
ans = "Undefined";
}
channel.sendMessage("The answer is: `" + ans + "`").queue();
return new CommandResult(CommandResultType.SUCCESS);
}
}
}
public CommandResult queryWolfram(String operation, TextChannel channel) {
channel.sendTyping().queue();
try {
CompletableFuture<CommandResult> result = new CompletableFuture<>();
WebSocket socket = new WebSocketFactory().createSocket("wss://www.wolframalpha.com/n/v1/api/fetcher/results");
ArrayList<Integer> pos = new ArrayList<>(); //prevent duplicate
socket.addListener(new WebSocketAdapter() {
@Override
public void onTextMessage(WebSocket websocket, String message) {
try {
//System.out.println(message);
JSONObject resp = new JSONObject(new JSONTokener(message));
switch(resp.getString("type")) {
case "pods":
for(Object obj : resp.getJSONArray("pods")) { //pods might have multiple values
JSONObject pod = (JSONObject) obj;
if(pod.getBoolean("error")) continue; //skip errors
if(!pos.contains(pod.getInt("position"))) { //check dupe
//build big image for each pods
ArrayList<BufferedImage> images = new ArrayList<>();
int width = 0, height = 0;
if(!pod.has("subpods")) continue; //ignore empty pods that doesnt have image, usually fixed somewhere else
for(Object subobj : pod.getJSONArray("subpods")) {
JSONObject subpodImg = ((JSONObject) subobj).getJSONObject("img");
images.add(ImageIO.read(new URL(subpodImg.getString("src"))));
if(subpodImg.getInt("width") > width) width = subpodImg.getInt("width"); //get widest image and use it as final width
height += subpodImg.getInt("height"); //add all images
}
//create final image
BufferedImage podImg = new BufferedImage(width + 20, height + 20, BufferedImage.TYPE_INT_RGB); //padding
Graphics g = podImg.getGraphics();
g.setColor(new Color(255, 255, 255)); //fill as white first
g.fillRect(0, 0, width + 20, height + 20);
int y = 10;
for(BufferedImage img : images) {
g.drawImage(img, 10, y, null);
y += img.getHeight();
}
//send each pod as an individual message
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(podImg, "png", os);
channel.sendMessage(pod.getString("title") + ":")
.addFile(new ByteArrayInputStream(os.toByteArray()), "result.png").queue();
pos.add(pod.getInt("position")); //update to prevent dupes
}
}
break;
case "futureTopic":
result.complete(new CommandResult(CommandResultType.FAILURE, "This query was identified under the topic of `" + resp.getJSONObject("futureTopic").getString("topic") + "`; Development of this topic is under investigation..."));
break;
case "didyoumean":
result.complete(new CommandResult(CommandResultType.INVALIDARGS, "No good results found :cry:\nDid you mean `" + resp.getJSONArray("didyoumean").getJSONObject(0).getString("val") + "`?"));
break;
case "noResult":
result.complete(new CommandResult(CommandResultType.NORESULT));
break;
case "queryComplete": //might provide no output for certain queries, but theres no practical way to detect with this listener rn
websocket.disconnect();
result.complete(new CommandResult(CommandResultType.SUCCESS)); //if its preceded by anything it wouldnt update; thats how complete() works
break;
}
} catch(Exception e) {
result.complete(new CommandResult(CommandResultType.ERROR, ExceptionUtils.getStackTrace(e)));
}
}
});
//System.out.println("{\"type\":\"init\",\"lang\":\"en\",\"exp\":" + System.currentTimeMillis() + ",\"displayDebuggingInfo\":false,\"messages\":[{\"type\":\"newQuery\",\"locationId\":\"hipuj\",\"language\":\"en\",\"displayDebuggingInfo\":false,\"yellowIsError\":false,\"input\":\"" + operation + "\",\"assumption\":[],\"file\":null}],\"input\":\"" + operation + "\",\"assumption\":[],\"file\":null}");
socket.connect();
socket.sendText("{\"type\":\"init\",\"lang\":\"en\",\"exp\":" + System.currentTimeMillis() + ",\"displayDebuggingInfo\":false,\"messages\":[{\"type\":\"newQuery\",\"locationId\":\"hipuj\",\"language\":\"en\",\"displayDebuggingInfo\":false,\"yellowIsError\":false,\"input\":\"" + operation + "\",\"assumption\":[],\"file\":null}],\"input\":\"" + operation + "\",\"assumption\":[],\"file\":null}");
return result.get();
} catch (IOException | WebSocketException | InterruptedException | ExecutionException e) {
return new CommandResult(CommandResultType.ERROR, ExceptionUtils.getStackTrace(e));
}
}
}

File Metadata

Mime Type
text/x-java
Expires
Mon, Jul 7, 4:43 AM (1 d, 10 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
00/a4/7c002d00ad6791438123d43ab96a

Event Timeline