Exit Chat Window When Finished In Unity - c#

I'm trying to build an interface so I can load a chat window with
messages I can read in the window. The user presses enter and the message index is incremented
so the next message is displayed. After the last message is displayed for
e.g. lvl 7, event 1 I would like the window to close.
The 3 parameters are the level, event, messageindex.
What happens is I don't see the chat window and no messages are
displayed in the window. How can i modify the algorithm so
that I read all the messages for the level and event and then
the window closes properly?
...
Debug.Log("File size is" + sizeoffile);
for (int i = 0; i < sizeoffile; i++)
{
if ((storyitemData["storyline"][i]["event"].ToString() == eventno.ToString()) & (storyitemData["storyline"][i]["level"].ToString() == levelno.ToString()) & (storyitemData["storyline"][i]["index"].ToString() == msgindex.ToString()))
{
Debug.Log("read message was called with message index " + msgindex + " and the content is " + storyitemData["storyline"][i]["content"].ToString());
//check that this is right
txtlbl.GetComponent<Text>().text = storyitemData["storyline"][i]["content"].ToString();
}
else if ((storyitemData["storyline"][i]["event"].ToString() == eventno.ToString()) & (storyitemData["storyline"][i]["level"].ToString() == levelno.ToString()) & (storyitemData["storyline"][i]["index"].ToString() != msgindex.ToString()))
{
msgindex = 1;
chatwindow.active = false;
}
}
Example JSON
{
"storyline":[
{
"level":1,
"event":1,
"index":1,
"content":"hello"
},
{
"level":1,
"event":1,
"index":2,
"content":"yes I saw that"
},
{
"level":7,
"event":1,
"index":1,
"content":"can I buy a sandwhich?"
},
{
"level":7,
"event":1,
"index":2,
"content":"thank you"
},
{
"level":7,
"event":1,
"index":3,
"content":"Salt please"
},
{
"level":7,
"event":2,
"index":1,
"content":"Java was"
},
{
"level":7,
"event":2,
"index":2,
"content":"my first language"
}
]
}

There are numerous ways you can handle this and without more code is hard to determine exactly what your setup is. All you have really shown us is that you are passing in a specific index to the list but for some reason still iterating over a list with a size of sizeoffile which is not mentioned at all.
I am also not sure if you intended this, but in your if conditionals, you are not using a && AND operator, but a bit-wise & AND operator, which is different.
You can simply add another conditional check first to see if the current index you are reading is about to exceed the container type you are using.
if((storyitemData["storyline"].Count) <= msgindex)
{
// we reached the end of the container, so disable our chat window
}
else if((storyitemData["storyline"][i]["event"].ToString() == eventno.ToString()) & (storyitemData["storyline"][i]["level"].ToString() == levelno.ToString()) & (storyitemData["storyline"][i]["index"].ToString() == msgindex.ToString())))
{
...
}
If what I have mentioned does not work, please add more detail to your question, and a bit more code would not hurt either. Adding the original container of the structure you are serializing to JSON would help. Is there a reason you are serializing an entire chat log to JSON to pass around your game?

Related

Prevent page load every time on Whatsapp Automation using selenium- C#

I am developing a automation of Whatsapp using silenium and C# with web whatsapp for my personal reason.
I am currently stuck in 2 problems
My number get blocked on sending message where as i had already places delay of 10-15 seconds in each request.
Each time my page reload on whastapp call i need to prevent it and want to place message directly any way for it ?
Note- numbers are dynamic and coming from DB.
Code
private void msgnew(string number, string message, int len, string oldnumber)
{
driver.Navigate().GoToUrl("https://web.whatsapp.com/send?phone=" + number + "&text=" + Uri.EscapeDataString(message) + "&lang=en&app_absent=1");
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(30);
driver.FindElement(By.CssSelector("button._4sWnG>span")).Click();//Click SEND Arrow Button
}
you can do it in js as:
js = """
var [ num ] = [ arguments[0]];
function openChat (t) {
var e;
t&&((e=document.createElement("a")).setAttribute("href","whatsapp://send?phone="+t),document.body.appendChild(e),e.click(),e.outerHTML="",setTimeout(1,1e3))
}
return openChat(num)
"""
now use ExecuteScript ,
in python :
js = """
var [ num ] = [ arguments[0]];
function openChat (t) {
var e;
t&&((e=document.createElement("a")).setAttribute("href","whatsapp://send?phone="+t),document.body.appendChild(e),e.click(),e.outerHTML="",setTimeout(1,1e3))
}
return openChat(num)
"""
self.driver.execute_script(js, number)
and to check if current number opened:
js = """
var [ t ] = [ arguments[0]];
if (document.querySelectorAll(`[data-id*="${t}#"]`).length > 0 || (document.querySelector(`#main header span[title]`) && document.querySelector(`#main header span[title]`).title.replace(/\s/g, '').replace('-', '').replace('+','').replace('⁩', '').replace('⁦', '') == t)
){
return true
}
"""
r = self.driver.execute_script(js, number)
r will be true if open current number.

"The process cannot access the file because it is being used by another process." with SystemReader

I have no coding experience but have been trying to fix a broken program many years ago. I've been fumbling through fixing things but have stumbled upon a piece that I can't fix. From what I've gathered you get Alexa to append a Dropbox file and the program reads that file looking for the change and, depending on what it is, executes a certain command based on a customizable list in an XML document.
I've gotten this to work about five times in the hundred of attempts I've done, every other time it will crash and Visual Studio gives me: "System.IO.IOException: 'The process cannot access the file 'C:\Users\\"User"\Dropbox\controlcomputer\controlfile.txt' because it is being used by another process.'"
This is the file that Dropbox appends and this only happens when I append the file, otherwise, the program works fine and I can navigate it.
I believe this is the code that handles this as this is the only mention of StreamReader in all of the code:
public static void launchTaskControlFile(string path)
{
int num = 0;
StreamReader streamReader = new StreamReader(path);
string str = "";
while (true)
{
string str1 = streamReader.ReadLine();
string str2 = str1;
if (str1 == null)
{
break;
}
str = str2.TrimStart(new char[] { '#' });
num++;
}
streamReader.Close();
if (str.Contains("Google"))
{
MainWindow.googleSearch(str);
}
else if (str.Contains("LockDown") && Settings.Default.lockdownEnabled)
{
MainWindow.executeLock();
}
else if (str.Contains("Shutdown") && Settings.Default.shutdownEnabled)
{
MainWindow.executeShutdown();
}
else if (str.Contains("Restart") && Settings.Default.restartEnabled)
{
MainWindow.executeRestart();
}
else if (!str.Contains("Password"))
{
MainWindow.launchApplication(str);
}
else
{
SendKeys.SendWait(" ");
Thread.Sleep(500);
string str3 = "potato";
for (int i = 0; i < str3.Length; i++)
{
SendKeys.SendWait(str3[i].ToString());
}
}
Console.ReadLine();
}
I've searched online but have no idea how I could apply anything I've found to this. Once again before working on this I have no coding experience so act like you're talking to a toddler.
Sorry if anything I added here is unnecessary I'm just trying to be thorough. Any help would be appreciated.
I set up a try delay pattern like Adriano Repetti said and it seems to be working, however doing that flat out would only cause it to not crash so I had to add a loop around it and set the loop to stop when a variable hit 1, which happened whenever any command types are triggered. This takes it out of the loop and sets the integer back to 0, triggering the loop again. That seems to be working now.

How can I get a message if a string does not exist?

I'm attempting to read a text file and delete a user entered string. I cannot get it to report a message if the string does not exist.
I cannot explain everything I've tried to this point, it's been many things. I know there is nothing in it's current form that would give me the results I expect, but I've tried many many things and this is currently where it's at. For the code that is there, it's doing everything I'm telling it to do.
if (rButtonDelete.Checked)
{
bool isValid = txtID.Text.Length < 5;
if (txtID.Text == "")
{
lbOne.Items.Add("You must enter a fixture to delete.");
}
else
if(!isValid==false)
{
lbOne.Items.Add("Enter full fixture ID to delete.");
}
else
{
var oldLines = System.IO.File.ReadAllLines(#"F:\09 Quality\CMM Fixtures\fixtures.txt");
var newLines = oldLines.Where(lines => !lines.Contains(txtID.Text));
System.IO.File.WriteAllLines(#"F:\09 Quality\CMM Fixtures\fixtures.txt", newLines);
lbOne.Items.Add(txtID.Text + " was deleted.");
}
}
As stated above, as it exists now, it does everything I am telling it to do. I just need to report that a string being searched for does not exist if in doesn't. No matter what I type into the text box, it tells me it's been deleted, even if it doesn't exist.
How about this:
if (oldLines.Count() == newLines.Count())
{
lbOne.Items.Add(txtID.Text + " does not exist.");
}
else
{
lbOne.Items.Add(txtID.Text + " was deleted.");
}

Sending a keypress to the active window that doesn't handle Windows message in C#

When I am detecting a pixel with a given color, I want to send the Key "k".
The problem is that even though the window is active, wit the following code it sends me an exception : SendKeys cannot run inside this application because the application is not handling Windows messages. Either change the application to handle messages, or use the SendKeys.SendWait method. The Sendwait method doesn't seem to press the key fast enough (but at least it gives no exception). I don't really care if the required solution is "dirty", it's a poc I'll use once
static void Main(string[] args)
{
string ligne;
string previousligne = string.Empty;
int compteur = 0;
while (true)
{
Color pixColor = Win32.GetPixelColor(System.Windows.Forms.Cursor.Position.X, System.Windows.Forms.Cursor.Position.Y);
ligne = pixColor.Name;
if (previousligne != ligne)
{
if (ligne == "ffcecefe")
{
SendKeys.Send("k");
}
Console.WriteLine(ligne);
System.IO.File.AppendAllText(#"C:\Users\Public\WriteLines.txt", "-----" + DateTime.Now.Minute + ":" + DateTime.Now.Second + ":" + DateTime.Now.Millisecond + " = " + ligne);
previousligne = ligne;
compteur++;
if (compteur % 10 == 0)
{
System.IO.File.AppendAllText(#"C:\Users\Public\WriteLines.txt", "---------" + compteur);
Console.WriteLine("---------" + compteur);
}
}
}
}
If you know Final Fantasy X, I'm trying to automate the process of avoiding the lightning bolts : video
I could just cheat to get the ingame result (or do it the legit way) and it would have already been done, but if I can learn a bit more of C# instead it would be better.
The console window (i.e. your running process) is the active window which SendKeys is sending data to. Since the console doesn't have a message loop, there is nowhere for the message to be received at, and it's lost. You would need to activate the target window with something like SetActiveWindow().
See also How do I send key strokes to a window without having to activate it using Windows API?

Using webdriver PageFactory to pick certain page

I have a web project where clicking a button navigates to another page. The new page can be 1 of three possible pages depending on data in the server. (The url may be the same for 2 of those pages)
I have three classes representing expected elements on each page using the PageObject model.
What is the best way to actually find what page actually got loaded? Is there an OR type of wait that I can wait on three unique elements and get the one that actually got loaded?
Yes, it is possible to check the presence of unique element (which identifies the page) and then return respective page in the framework.
However, a test should know the page it is expecting next and should assume that the correct page has loaded and perform further actions/assertions. You can even put an assertion here to verify correct page has loaded. If a different page has loaded, then the test eventually fails as assertions would fail.
This way test becomes more readable and describes flow of application.
Also, setting up test data upfront for the tests, is always advisable. This way you would know what data is available on server and test would know which page would render.
I had a similar issue where I needed to detect if a login was for a new user (the login page then goes to a terms & conditions page rather than direct to the home page).
Initially I just waited and then tested the second page but this was just a pain so I came up with this.
To Test the result with this:
var whichScreen = waitForEitherElementText(By.CssSelector(HeaderCssUsing), "HOME SCREEN", "home", terms.getHeaderLocator(), terms.headerText, "terms", driver, MAX_STALE_RETRIES);
if(whichScreen.Item1 && whichScreen.Item2 == "terms")
{
terms.aggreeToTerms();
}
The method that this calls is :
protected Tuple<bool, string> waitForEitherElementText(By locator1, string expectedText1, string return1Ident,
By locator2, string expectedText2, string return2Ident, IWebDriver driver, int retries)
{
var retryCount = 0;
string returnText = "";
WebDriverWait explicitWait = new WebDriverWait(driver, TimeSpan.FromSeconds(globalWaitTime));
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(0.5));
while (retryCount < retries)
{
try
{
explicitWait.Until<bool>((d) =>
{
try
{
if (Equals(d.FindElement(locator1).Text, expectedText1)) { returnText = return1Ident; };
}
catch (NoSuchElementException)
{
if (Equals(d.FindElement(locator2).Text, expectedText2)) { returnText = return2Ident; };
}
return (returnText != "");
});
return Tuple.Create(true, returnText);
}
catch (StaleElementReferenceException e)
{
Console.Out.WriteLine(DateTime.UtcNow.ToLocalTime().ToString() +
":>>> -" + locator1.ToString() + " OR " + locator2.ToString() + "- <<< - " +
this.GetType().FullName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name +
" : " + e.Message);
retryCount++;
}
}
return Tuple.Create(false,"");
}
The explicit wait until uses a boolean so will loop around for the full wait time (I have a very slow Test server so I set this to 60 seconds). the implicit wait is set to half a second so the element tests will attempt every half a second and loop around until either true is returned or it fails.
I use a Tuple so that I can detect which screen I am on, and in this case agree to the terms & conditions which then sets me back on my normal page path

Categories

Resources