I made a twitch irc bot.
I have setup a little "system" to turn itself on whenever the stream is going online and should turn off when the stream isnt online anymore.
im using the following code:
if (TwitchStatus.isstreamlive && multistartprepare == false && multistartprepare2 == false){
livemode = true;
multistartprepare = true;
startedAt = DateTime.now();
startup();
}else{
if (TwitchStatus.isstreamlive == false && multistartprepare){
livemode = false;
multistartprepare = false;
multistartprepare2 = false;
TTmsg.cancel();
TTmsg.purge();
}
}
isstreamlive is a boolean which is either true when a stream is live or false when the stream is offline.
isstreamlive gets updated every 5 secons by making a JSON request and holds the right value the whole time.
the problem now is that the startup() Method will activate a timer for a greeting message in the irc chat. Somehow it happens the timer got executed 2 or 3 times when i start my bot so i guess something is wrong with my if else statement.
the booleans multistartprepare and multistartprepare2 are false on start and are there for the bot to start only once a time, til the stream is over and he can get offline.
is there something wrong above? Guess the code gets executed to many times.
greetings and sorry for bad english :D
It might help if you use your livemode variable in the if as well
if (TwitchStatus.isstreamlive &&
!multistartprepare &&
!multistartprepare2 &&
!livemode) {
You might be able work around this by setting up a timeout that prevents your bot from sending the message if it's been sent in the past few seconds.
long lastSent = 0;
...
if (System.currentTimeMillis() - lastSent > 1000*5) { // 5 seconds elapsed
...
// send message
lastSent = System.currentTimeMillis();
}
You might have something wrong with your setup method, or the server might be sending you multiple went-online messages, but it's hard to tell based on the info you have so far.
Related
I'm aware or the Thread.sleep() and postDelayed() function in java/androidStudio.
But here is the issue, I'm creating a replicate of Simon says game.
I created a generateSequence() function that puts number of 1-9 randomly into an array called sequence. After that, I need to display these sequence, which basically changes the background of a textView for a second and then back to its original background using the postDelayed() function.
Here is my code:
private void displaySequence(){
for(int i = 0; i < sequence.size(); i++) {
if(sequence.get(i) == 1) {
viewCard11.setBackgroundResource(R.drawable.text_view_circle4);
proceed = false;
handler.postDelayed(() -> {
viewCard11.setBackgroundResource(R.drawable.text_view_circle3);
proceed = true;
}, 1000);
}
else if(sequence.get(i) == 2) {}
else if(sequence.get(i) == 3) {}
else if(sequence.get(i) == 4) {}
else if(sequence.get(i) == 5) {}
else if(sequence.get(i) == 6) {}
else if(sequence.get(i) == 7) {}
else if(sequence.get(i) == 8) {}
else if(sequence.get(i) == 9) {}
while(!proceed) {}
}
}
But the problem with postDelayed() is that only whatever is inside the function is delayed. Meaning if this sequence had 2 element, it will simultaneously blink the background. The for loop doesn't wait for the postDelayed to finish whatever it is suppose to do, but instead it increments and proceed to put the next postDelayed.
To solve this issue, I tried to use a proceed boolean variable as a delay. What I do is that, before we call the postDelayed, I set proceed as false. Since it will not wait for postDelayed(), it will go to the next line of code which is the while loop.
By setting the proceed as false, I use it to create a infinite loop. But this infinite loop will be broken by the completed postDelayed() as proceed will be set to true in it, then the code can continues the for loop.
But I not sure why it simply doesn't work. When I run the code, it just displayed a blank screen. It seemed like the problem resides within the infitine while loop and postDelayed() can't update the proceed variable.
I tried using Thread.sleep(1000) as a replacement of postDelayed, but during startup, the program simply shows a white background for however long the parameter is passed to Thread.sleep()
I have exhausted my option and I hope someone has a better idea.
Thank you.
The loop does not wait for the postDelayed because what's inside the postDelayed happens async. This means that it works independently from the UI thread, on a second thread. What you want to accomplish is to make the UIthread wait for a period of time, and not start another thread after a specific period.
You could try to use the handler in this way:
Handler handler=new Handler()
{
public void handleMessage(Message msg)
{
if(msg.what==0)
{
viewCard11.setBackgroundResource(R.drawable.text_view_circle3);
proceed = true;
}
}
};
and then you may use the handler like this:
handler.postDelayed(() ->
{
//does nothing just waits 1 second and then send empty message
handler.sendEmptyMessage(0)
}, 1000);
Foreword: I apologise if this is a very silly error or something that is in fact well-documented. To me right now it seems very strange and makes absolutely no sense.
The Application
I have a Java command-line application built in IntelliJ IDEA Ultimate on macOS 10.13.4 that makes use of four Maven libraries listed below. Its purpose is to download files from a website, and navigates across paginated results in doing so.
One of this application's features is the ability to keep running in a loop, checking for new results if enough time has passed by the time it finishes its current scan. To do this, it calls Thread.sleep(remainingMillis) as part of the while condition in a do-while block.
The Problem
The application worked without any issues, but after introducing the Thread.sleep() call (I suspect this is the troublesome line anyways), some very strange behaviour occurs: The application performs the first run without issues, fetching three items from the configured website; it is then configured to ensure that 60 seconds have passed before running again. However upon consequent runs, rather than scan the first page of results, logs indicate that it starts looking at page 31 (as an example), where it finds no results. Having failed to find anything, attempt two of three looks at page 32, and the final attempt looks at page 33; it then once again waits until 60 seconds have passed since the scan iteration began.
I can't confirm this, but it seems as though it then continues this count in subsequent scans: 34, 35, then 36, and waiting again. However, the code would suggest that this should have started at 1 again when another iteration of the while starts up.
This could have been IntelliJ or Java playing up, and it may have simply required cleaning out the bin/obj folders, but if this is something due to my code, I would much rather know about it so I don't encounter the same silly issue in the future.
The Observations
Having just run the application a few days later with the current configuration means that it doesn't call Thread.sleep(), as more than 60 seconds pass so it continues with the next iteration immediately; when this happens, the weird page index incrementing issue doesn't rear its head - instead the next iteration continues from page 1 as it should.
Afterwards, running it such that it did Thread.sleep() for several seconds before starting the next iteration didn't cause a problem either... very strange. Was this a dream?
The Code
Sidenote: I added Thread.currentThread().interrupt() to try and fix this issue, but it didn't seem to have an effect.
public static void main(String[] args) {
do {
startMillis = System.currentTimeMillis();
int itemsFetched = startFetching(agent, config, record, 1, 0);
} while (shouldRepeat(config.getRepeatSeconds(), startMillis));
}
private static boolean shouldRepeat(int repeatSeconds, long startMillis) {
long passedMillis = System.currentTimeMillis() - startMillis;
int repeatMillis = repeatSeconds * 1000;
boolean repeatSecondsReached = passedMillis >= repeatMillis;
if (repeatSeconds < 0) {
return false;
} else if (repeatSecondsReached) {
return true;
}
long remainingMillis = repeatMillis - passedMillis;
int remainingSeconds = (int) (remainingMillis / 1000);
try {
Thread.sleep(remainingMillis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
return true;
}
private static int startFetching(Agenter agent, MyApplicationConfig config, MyApplicationRecord record, int pageIndex, int itemsFetched) {
String categoryCode = config.getCategoryCode();
List<Item> items = agent.getPageOfItems(categoryCode, pageIndex, config);
if (items == null) {
return itemsFetched;
}
int maxItems = config.getMaxItems();
try {
for (Item item : items) {
String itemURL = item.getURL();
agent.downloadItem(itemURL, config, item.getItemCount());
itemsFetched++;
if (maxItems > 0 && itemsFetched >= maxItems) {
return itemsFetched;
}
}
} catch (IOException e) {
// Log
}
return startFetching(agent, config, record, pageIndex + 1, itemsFetched);
}
}
Maven Libraries
commons-cli:commons-cli:1.4
org.apache.logging.log4j:log4j-api:2.11.0
org.apache.logging.log4j:log4j-core:2.11.0
org.jsoup:jsoup:1.11.2
Check your Agenter implementation, in the call of
agent.getPageOfItems the pageIndex is supplied but could be stored there in an instance variable or something like that. The error itself might be that on additional calls it probably didn't get reset (correctly).
I'm trying to detect mode when we in call. I'm using most popular example with broadcast and telephonyManager.
But there are only 3 states.
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if(state.equals(TelephonyManager.EXTRA_STATE_RINGING)){
}
if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
}
if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)){
}
after some tests i found that :
1) when incoming call - than i see state = RINGING
- accept call from this state = OFFHOOK
2) but when im do outgoing call - state = OFFHOOK , and when another "me" on other side accept call - state still = OFFHOOK.
How to correctly detect IN_CALL_MODE (mean im speaking at current time ). ?
Can any help ?
How about using AudioManager??
AudioManager manager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
if(manager.getMode()==AudioManager.MODE_IN_CALL){
return true; // Active call
}
else {
return false;
}
My program is coded in Java. I have an IF() check in run() method (in a Thread). In the IF check, if the condition is satisfied, it shows a Window dialog (using JOptionPane.showMessageDialog) with OK button. However, it shows infinitely. When I click OK it pops up again and again. How can I end the if check after the user click OK. Or when the condition is met, it only shows once ?
This is my method()
public void danhHoiWumpus()
{
if ((GameScreen.bg[x[0] + 1][y[0]] == 2) || (GameScreen.bg[x[0] + 2][y[0]] == 2) || (GameScreen.bg[x[0] + 3][y[0]] == 2) || (GameScreen.bg[x[0]][y[0]+1] == 2) || (GameScreen.bg[x[0]][y[0]+2] == 2) || (GameScreen.bg[x[0]][y[0]+3] == 2))
{
JOptionPane.showMessageDialog(this, "Có mùi wumpus ! \n Bạn được học bổng 40%");
}
}
This is my run() method
public void run()
{
while(true)
{
hunter.update();
hunter.danhHoiWumpus();
// i++;
repaint();
// System.out.println("Gia tri cua y la " +i);
try {
thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The idea of this action is. When the RED square is going near the YELLOW square, it will pop up a dialog "I smell Wumpus". When the user click OK. They will choose to shot the wumpus (I will do this later).
And here is my full source code (for reference):
https://www.mediafire.com/?wkp6hyq32nq23mp
Thank you in advance.
Your code is executing in an infinite while loop
while(true)
// I am infinite
}
The term you are looking for is hit detection. There are a myriad of ways to achieve it. Look up hit detection in Java for some pointers.
What you have isn't necessarily wrong though.
while (true) // I'm not always bad!
is used in a lot of applications. However, while your code isn't completely posted, I don't see anywhere you break from this. You may be interested in the
java.util.Timer
and the
java.util.TimerTask
Both of those have wide application in Java game development
Your sleep time is too low (20 nanoseconds). Increase the time, otherwise it will happen too quick for you to understand it.
You are potentially triggering this if condition many many times.
You need some 'rising edge trigger' logic in order to only trigger when the new value goes from false to true, instead of triggering whenever it's true.
currentValue = bigLongLogicCheck;
if(!oldvalue&¤tValue) {alert()}
oldvalue = currentValue
I'm trying to assert the fact I have received 10 messages from pubnub. I do infact receive them to the console. However what would be the right way to assert that I have. I'm not entirely sure on what syntax I should use.
#Test
public void testPublisher() throws PubnubException {
// Send 10 messages
for(int i = 0; i <= 10; i++){
service.publish("my_channel", "Message: " + i);
}
// Wait until we have recieved the 10 messages
do{}while(service.count() <= 10);
// For each message print out the details
service.getMessages().forEach(System.out::println);
assertArrayEquals(service.count());
}
You should be able to use
assertTrue(service.count() == 10);
Your do...while loop is known as a "busy spin" which is considered an anti-pattern in most cases and should be avoided. Busy spinning thrashes the CPU whilst it waits and your implelemtation could also run eternally if something goes wrong and 10 messages aren't received.
https://en.wikipedia.org/wiki/Busy_waiting
You should consider a blocking mechanism... possibly with a timeout such as
BlockingQueue.take() or BlockingQueue.poll() or CountdownLatch.await()