This is an oddly specific question but I'm trying to get the EventWaiter from JDA Utilities to work. (https://github.com/jagrosh/ExampleBot/tree/master/src/main/java/com/jagrosh/examplebot)
I have a method set up and the time out section works, but the waiter doesn't seem to pick up any new messages sent to discord like it is supposed to and I'm not sure why. Here is what I have:
public static void askQuestions(int numLeft, MessageReceivedEvent event, String level) {
if(numLeft==0) {
Writer.listWords(event);
Writer.clearWords();
return;
}
//Get random line from text file and store in text.
text = Reader.fileReader(level);
//Get the question
word = getQuestion(text);
//Get the answer
ans = getAnswer(text, event);
//Write word to txt file to print out later at end of game.
Writer.playedWordsWrite(word, ans);
//Create image of word and send to discord
imageCreator(word, event);
//Set up waiter to get players' answers. Mention user who gets it right and then call the method again.
waiter.waitForEvent(MessageReceivedEvent.class,
//Make sure it's the right answer in the same channel
e -> e.getChannel().equals(event.getChannel()) && e.getMessage().getRawContent().equals(ans),
//Respond, inserting the name they listed into the response
e -> {
e.getChannel().sendMessage(e.getAuthor().getAsMention()+ " got it right!").queue();
askQuestions(numLeft-1, e, level);
},
//If the user takes more than 10 seconds, time out
7, TimeUnit.SECONDS, () -> {
event.getTextChannel().sendMessage("Correct answer: "+ans).queue();
askQuestions(numLeft-1, event, level);
}
);
}
The best practice is not to store JDA objects, such as channels, because it would be better to compare their IDs as longs. It's possible that that's the issue. Try e.getChannel().getIdLong() == event.getChannel().getIdLong() otherwise, I'd guess its one of your methods such as imageCreator or playedWordsWrite
Related
In Java, when you print to the console while a user is typing. It will destroy what is being typed. Let's say I have a server set up, and you can run commands from the server. Then this is what it might look like.
I'm trClient connected to server
ying to typMessage received from client
e a command
Is there a way to get around this? To have the text be printed on the line above the user is typing on. If you've ever ran a Minecraft server, you might know what I'm talking about. It would look something like this.
Since Minecraft is made using Java, I know that this is possible, but I haven't been able to figure out a way to do it.
Maybe you could do it like this.
You have one while loop with a value of true.
Everything that the user enters is entered in the ArrayList and every time the user enters something that list is printed.
If you want it to print only the entered message, you can empty it each time you print the list.
There you could use LinkedList where when you drag all the variables from the list, it remains empty.
If you want to use a library that gives terminal support, you can use com.googlecode.lanterna for your own terminal where you can set where you want to show the inputs given by the user. You can add the dependency to your program:
<!-- https://mvnrepository.com/artifact/com.googlecode.lanterna/lanterna -->
<dependency>
<groupId>com.googlecode.lanterna</groupId>
<artifactId>lanterna</artifactId>
<version>3.1.1</version>
</dependency>
You can use the Terminal of this library and do such manual positioning of input and printed test like the way you want the interface.
Have a our on this page and browse more to gather knowledge on lanterna.
I've added a very basic code for reading input and showing that on the gui:
public static void main(String[] args) {
try {
int row = 5, col = 5;
Terminal terminal = new DefaultTerminalFactory().createTerminal();
Screen screen = new TerminalScreen(terminal);
TextGraphics tg = screen.newTextGraphics();
screen.startScreen();
KeyStroke key;
List<Character> string = new ArrayList<>();
while (true) {
System.out.println("reading input");
key = terminal.readInput();
if (key != null && key.getCharacter() != null) {
System.out.println("Key not null: " + key.getCharacter());
// you can add more keypress checks, they have a lot of enums for this
if (key.getKeyType() == KeyType.Enter) {
String str = string.stream().map(String::valueOf).collect(Collectors.joining());
System.out.println(col + " " + row + " " + str);
tg.putString(col, row, str);
string.clear();
} else if (key.getKeyType() == KeyType.Escape) {
break;
} else {
string.add(key.getCharacter());
}
} else {
System.out.println("Null input");
break;
}
screen.refresh();
}
screen.stopScreen();
System.exit(0);
} catch (Exception e) {
e.printStackTrace();
}
}
So I've made an app that makes sentences, much like a keyboard of words and pictures, what I'd like to achieve is a kind of predictive text where if a user chooses X they are shown Y and Z, user doesnt want either of these and chooses A.
The next time the user picks X they are shown A, Y and Z, so it learns like your keyboard would, my words are stored in a database and right now i have a crude solution where if the user chooses X they are shown Y and Z, and I also track how many times each card is clicked and show them too but it has no context of full sentences or previously made sentences, i hope this is making sense as I've no idea where to start I've been looking at maybe a hashmap full of essentially TAGS as key value pairs and adding to it but I need to research this, I've also looked at candidate view but that would mean declaring my app as an Input Method I believe and I need the normal keyboard for other things, but I'm not sure how that works or if it's remotely viable so I'm hoping someone can educate me here or point to a better solution.
Below I'll post excerpts of what I'm doing thus far
//Check what card was pressed and update predictedCardActivityDB example
//to carry on like this would mean a lot of typing
//and not a lot of smart results
if (cardsChoice.predictive == true) {
String item = cardWriter.getCardSpeech();
switch(item){
case " I":
String[] I_String = {"LIKE","LOVE","WANT"};
predictedCardActivityDB.prepareCardData
(I_String,getActivity(),prefString);
break;
case " I'm":
String[] Im_String =
{"HAPPY","SAD","ANGRY","HUNGRY","FEELING"};
predictedCardActivityDB.prepareCardData
(Im_String,getActivity(),prefString);
break;
And this is the prepareCardData method excerpt nothing to see here just updates the lists based on the string array
public static void prepareCardData
(String[] predictionArray, Context context ,String prefString){
//boring database stuff
DaoMaster.DevOpenHelper helper =
new DaoMaster.DevOpenHelper(context, "ADD_NEW_CARD", null);
SQLiteDatabase db = helper.getWritableDatabase();
DaoMaster daoMaster = new DaoMaster(db);
DaoSession daoSession = daoMaster.newSession();
addNewCardDao leaseDao = daoSession.getAddNewCardDao();
QueryBuilder qb = leaseDao.queryBuilder()
.orderDesc(addNewCardDao.Properties.Clicked);
QueryBuilder qb2 = leaseDao.queryBuilder()
.orderDesc(addNewCardDao.Properties.Clicked);
predictsList.clear();
String[] strings1 = {"ORIGINAL","SIMPLE","PHOTOS", "USER"};
switch (prefString){
case "PHOTOS":
if (predictionArray != null){
//qb gets any card clicked >2
//qb gets all favourites tagged by a boolean
qb.where(addNewCardDao.Properties.CardIconType.in(strings1),
qb.or(addNewCardDao.Properties.Clicked.ge(2),
addNewCardDao.Properties.Fav.ge(true)));
predictsList = qb.list();
//qb2 gets any card that matches a word from the passed in
//string array predictionArray
qb2 = leaseDao.queryBuilder();
qb2.where(addNewCardDao.Properties.CardIconType.in(strings1),
qb2.or(addNewCardDao.Properties.CardName.in(predictionArray),
addNewCardDao.Properties.CardTitle.in(predictionArray)));
temptList = qb2.list();
db.close();
temptList.addAll(predictsList);
predicts_card_adapter.notifyItemInserted(predictedCardActivityDB.temptList.size());
predicts_card_adapter.notifyDataSetChanged();
predicts_card_adapter = new predictsCardAdapter(temptList,itemTouchListener);
predictsrecyclerView.setAdapter(predicts_card_adapter);
}else{
qb.where(addNewCardDao.Properties.CardIconType.in(strings1),
qb.or(addNewCardDao.Properties.Clicked.ge(2),
addNewCardDao.Properties.Fav.ge(true)));
predictsList = qb.list();
//this should work
predicts_card_adapter.notifyDataSetChanged();
predicts_card_adapter = new predictsCardAdapter(predictsList,itemTouchListener);
predictsrecyclerView.setAdapter(predicts_card_adapter);
db.close();
System.out.println("else, predictsList size " + predictsList.size());
}
break;
}
//should be able t delete this and use the two commented out piecess of code above
//the result being the predicted cards coming first in the list
/*
predicts_card_adapter.notifyItemInserted(predictedCardActivityDB.temptList.size());
predicts_card_adapter.notifyDataSetChanged();
predicts_card_adapter = new predictsCardAdapter(temptList,itemTouchListener);
predictsrecyclerView.setAdapter(predicts_card_adapter);
*/
}
I'm trying to make a 2d game using java microedition and i just want to make my control smoother but the problem is when i press the LEFT key while pressing the UP Key the condition is not working i dont know why
public void moveJet2() throws IOException{
int gameAction = getKeyStates();
if(gameAction==LEFT_PRESSED && gameAction==UP_PRESSED){
padX-=padXVel;
padY-=padYVel;
}
else if(gameAction==RIGHT_PRESSED){
padX += padXVel;
}
else if(gameAction==UP_PRESSED){
padY-=padYVel;
}
else if(gameAction==DOWN_PRESSED){
padY+=padYVel;
}
}
getKeyStates() returns the state of keys in a single int. The various keys have individual values. UP_PRESSED = 0x0002 and LEFT_PRESSED = 0x0004. So if you press UP on your d-pad while calling getKeyStates(), you'll get 2 back, and if (getKeyStates()==UP_PRESSED) will thus be true.
Likewise, if you press LEFT on your d-pad while calling getKeyStates(), you'll get 4 back.
But if you press UP and LEFT at the same time, you can't get back 2 and 4 - because that's obviously 2 ints - and getKeyStates() only returns one int.
What you do get back though, is rather simple: 2 + 4 = 6.
So, asking if (getKeyStates()==6) will be true if pressing UP and LEFT at the same time. Or if (getKeyStates()==UP_PRESSED+LEFT_PRESSED).
Typically though, you would ask using bit-operators, like this:
public void moveJet2() throws IOException{
int gameAction = getKeyStates();
if((gameAction & LEFT_PRESSED)!=0) {
padX -= padXVel;
}
if((gameAction & RIGHT_PRESSED)!=0) {
padX += padXVel;
}
if((gameAction & UP_PRESSED)!=0) {
padY-=padYVel;
}
if((gameAction & DOWN_PRESSED)!=0){
padY+=padYVel;
}
}
Because using that approach will work with any of the 8 directions you can press at the same time.
What i am shooting for is to be able to take the input from my text field in my GUI and put it into an ArrayList. Then I need to check the array and see if I already have the Integer in the array. If so I need to remove both Integers so the Integer is no longer inside the array. I also need to be able to add the Integer if it is not a duplicate to the ArrayList.
The purpose of this is to be able to have users sign in with a number. The vision I have is for them to put their unique number in when they sign in or sign out (Like a time clock). If their number is not in the array, they are signing in. If their number is in the arraylist then they are signing out.
This is what i have for code so far, i am getting a problem with signing out. It keeps sending the second value in the array back as the only one able to sign out. I have tried fixing it and can't seem to figure out what is wrong. Let me know if it would be more helpful if i posted my whole program or if this code snippet is enough to figure it out.
Thanks,
private void btnSignInActionPerformed(java.awt.event.ActionEvent evt) {
// Get data from form and put it into an Array List
Integer txtUserSignInName = Integer.valueOf(txtUserSignIn.getText());
ArrayList<Integer> userSignInNumber = new ArrayList();
userSignInNumber.add(12345678); //sample data
userSignInNumber.add(55489563); //sample data
userSignInNumber.add(26489564); //sample data
userSignInNumber.add(78654865); //sample data
userSignInNumber.add(txtUserSignInName);
// Setting up HashSet so no duplicate data
Set<Integer> hashSet = new HashSet<>();
hashSet.addAll(userSignInNumber);
userSignInNumber.clear();
userSignInNumber.addAll(hashSet);
// Other settings needed
SimpleDateFormat df = new SimpleDateFormat("hh:mm:ss a");
String time = df.format(new Date());
if ((txtUserSignIn.getText() != null && txtUserSignIn.getText().isEmpty())) {
String userSignInErrorMessage = "Sorry, Please Try Again";
JOptionPane.showMessageDialog(new JFrame(), userSignInErrorMessage, "Incorrect Sign In",JOptionPane.ERROR_MESSAGE);
//setting focus
txtUserSignIn.setText("");
txtUserSignIn.requestFocus();
} else {
for(int i = 1; i < userSignInNumber.size(); i++) {
// If number is already in array, remove it
if(txtUserSignInName.equals(userSignInNumber.get(i))) {
userSignInNumber.remove((Integer)txtUserSignInName);
System.out.println(txtUserSignInName + " has signed out");
txtLoggedInUsers.append(txtUserSignInName + " has signed out at " + time + "\n");
break;
} else { // If number is not in the array, add it to the array
System.out.println(txtUserSignInName + " has signed in");
txtLoggedInUsers.append(txtUserSignInName + " has signed in at " + time + "\n");
break;
}
}
System.out.println(userSignInNumber);
}
}
Lists are not really suitable for what you are trying to do. You would be better off using one of the Set interface implementations. Sets provide fast contains()/add()/remove() methods that you can use, without generally having to iterate over all elements manually in a loop. And if you do need to quickly iterate over all elements for some reason, then a LinkedHashSet would work just fine. For example:
Set<Integer> signedIn = new LinkedHashSet<>();
...
if (signedIn.add(loginNumber)) {
// The set was modified, therefore this is a new login
} else {
// The number was already present, log-off the user.
signedIn.remove(loginNumber);
}
...
if (signedIn.contains(loginNumber)) {
// Allow the user to...
} else {
// Error, user not signed in
}
There are a number of problems with your implementation.
The loop starts at 1 when array indices start at 0, so you are skipping the first entry.
Then you always break out of the loop straight away after checking the 2nd item and so don't check any others.
A better approach would be to use a Set, not just to remove duplicates, but as a primary way to store who is signed in. Then you can check if a number is in the set easily with the contains method so you don't need to loop through manually (which means you don't have to deal with the problems associated with removing items from a list while you are looping through it).
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I want to try making a state machine, but I am fairly new to programming. I read something about a state transition table to switch between states if you input something. I do not quite understand how that works and how it translates to Java code. Can anyone please explain?
A state machine refers to a program that tracks states relative to user input.
I want to be able to input a string and then the progam gives a
message and the state changes. For example: "do work", the program
says:"going to work" and changes state. after a while it says"done
with working" and the state changes back. kind of like a very small
game
Using your example from the comments, we could do something like;
import java.util.Scanner;
enum GoingState {
TO_HOME,
TO_WORK,
TO_SHOP,
}
public class StateGame{
public static GoingState state = GoingState.TO_WORK;
public static void main(String args[]){
Scanner scanIn = new Scanner(System.in);
System.out.println("Where do you want to go?");
if(scanIn.nextLine().toLowerCase().contains("home")){
state = GoingState.TO_HOME;
System.out.println("Going home.");
}
else if(scanIn.nextLine().toLowerCase().contains("work")){
state = GoingState.TO_WORK;
System.out.println("Going to work.");
}
else if(scanIn.nextLine().toLowerCase().contains("shop")){
state = GoingState.TO_SHOP;
System.out.println("Going to the shop.");
}
else{
System.out.println("No valid input");
}
}
}
In the above example I am using enums to track state, but it could just as easily be an int or String, or an Object that tracks the state. This, of course, is an incredibly over simplified example.
State machines usually track which state transitions are possible (which I haven't done) using a state transition map (or table), which tell the program whether it can or should change from one type of state to another type of state.
A very simple example of a state map could be where there is only a linear progression to your states, ie in the example above only being able to go from home to work, work to the shops, and back again without being able to go directly from the shops to home or vice versa. Tracking this could be fairly simple, because you could put the states in an array and check if where the user wanted to go was one above or below the current state in the array.
I hope this helps.
It is not actually a machine. In the simplest case it is a program which simply has an integer variable called state. The program reads an integer input and depending upon the input and the current value of the state, it sets a new value of state.
if (state == 0 && input == 0) {
state = 1;
}
if (state == 1 && input == 1) {
state = 2;
}
if (state == 2 && input == 2) {
state = 3;
}
if (state == 3 && input == 4) {
state = 4;
}
if (state == 4 && input == 8) {
state = 5;
}
// many more such statements to cover all combinations of state and input values
Instead of such a long chain of if statements, you can use switch-case, or more sophisticatedly a class hierarchy or enums etc. But the concept should be clear based on the above.