Kotlin use variable used in a while loop - android-studio

I want to use a function in loop condition and reuse it in the loop, like this code in Java, but I want it in kotlin :
while ( (data = in.readLine()) != null ) {
System.out.println("\r\nMessage from " + clientAddress + ": " + data);
}
I tried copying this code in android studio to automatically convert to Kotlin and the code looks like this :
while (reader.readLine().also { line = it } != null) {
Log.d("Line", line)
lines.add(line)
}
So I managed to get the lines with var line = "" before the loop, but the loop doesn't stop when the reader is done getting the message sent from the socket.
My wish is to send 2 messages through the socket, so I try to get all lines of one message, and when the second one arrives, I have to clear my lines variable to get the next message, but I can't.
Thanks !

You can use reader.lineSequence() function:
reader.lineSequence().forEach {
Log.d("Line", it)
lines.add(it)
}
Or as suggested in documentation, you can improve it by using File.useLines() which automatically closes the File reader so you don't have to do it manually

Related

In Angular How to Run a Loop that hit Back-End one by one

From Angular When I send some parameter to my Node.js Backend that generate a big array
and got some error or timeout issue.
I wanted to send a limited parameter to back end by Loop.
So how to create this Loop that will hit back end -> then get response from back end -> then hit next loop one by one ???
N.B: Previously I create a for loop but that hit all together that didn't meet my need.
My Previous Angular Loop that didn't work well:
for (let i = 0; i < this.branchList.length ; i++) {
this.form.get('branch_code').setValue(this.branchList[i].branch_code);
this.salSub =
this.payrollService.submitForSalaryProcess(this.form.value,
this.cycleList)
.subscribe((data)=> {
if (data['isExecuted'] == false) {
this.commonService.showErrorMsg(data['message']);
} else {
this.salProcessList = data['data'];
}
this.salSub.unsubscribe();
}
)
};

Variable undefined when using .get()

I am coding a Discord bot and one of my features is a Member counter. So far I can point it in the right direction and as long as I use the actual id number is numerical form everything works fine. The moment I try to create and store the id in a variable however, it starts to tell me that it is undefined.
let setchan = ""
let guildid = 0
client.on('message', async message => {
if (!message.content.startsWith(prefix2) || message.author.bot) return;
const args = message.content.slice(prefix2.length).trim().split(" ");
const command = args.shift().toLowerCase();
if (command === 'memchan'){
setchan = args
message.channel.send("Channel set to: " + setchan)
} else if (command === 'count') {
total = client.guilds.cache.get(message.guild.id).memberCount
guildID = client.guilds.cache.get(message.guild.id)
message.channel.send("Current member count: " + total)
message.channel.send("Your server id is: " + guildID)
message.channel.send("Your channel id is set to: " + setchan)
message.guild.channels.cache.get(setChan).setName("Members: " + total)
}
});
works fine
message.guild.channels.cache.get(setchan).setName("Members: " + total)
Does not though.
I have used .toString() and tried to set it as a number instead of string. Can someone please tell me what I am doing wrong?
Created the variable as both num and string.
the error I am getting is: Cannot read property 'setname' of undefined.
There are a few issues with your approach.
The declaration of setchan is inside your command handler. This means that every time the command handler is executed (once per message) it is re-set to "". If you change this value in one execution of the command handler, it will not persist to any other execution.
Even if this were working properly, you are setting setchan = args. args is the result of a .split(" ") - it is an array of arguments, not just one. You need to get args[0] if you want to respect only the first argument.
This is a poor way to implement any kind of configuration variables. When your bot restarts, the current memory state is lost. Since you're holding these only in memory, that means users will need to run memchan again every time the bot restarts. Additionally, if your bot ever joins more than just one guild, users in each guild will overwrite other guilds configuration.
My recommendation: Ditch the current approach. What you should do is either store configuration data in a map (object, Map, etc) and write that map to disk as JSON, loading it from disk on startup, so that the data can persist between restarts - or use a proper database, either a RDBMS/ORM/other. Look into SQL databases, Mongo, sequelize, etc.
To fix your current approach: the setchan variable needs to be declared once at the beginning of the file. You can store it on the bot if you like, it is quite convenient to do so.
//top level
bot.setchan = ""
...
//in memchan command
bot.setchan = args[0]
//in count command
message.guild.channels.cache.get(bot.setchan).setName("Members: " + total)
So this is how I eventually worked it out without needing to store the channel id in a DB ( Iam trying to avoid any extra weight if I can). So instead of creating a variable I just pass the desired channels id as an arg. A user can then use their choice of already running mod bots like mee6, dyno, carl etc to use an automessage to tell my bot when to work.
client.on('message', async message => {
if (!message.content.startsWith(prefix2) || message.author.bot) return;
const args = message.content.slice(prefix2.length).trim().split(" ");
const command = args.shift().toLowerCase();
if (command === 'run') {
let setchan = args[0]
total = client.guilds.cache.get(message.guild.id).memberCount
message.channel.send("Current member count: " + total)
message.guild.channels.cache.get(setchan).setName("Members: " + total)
message.delete()
}
});
Then deletes the command (as I havent added a role check yet)...
Thank you kuso and klay!

P4API.net: how to use P4Callbacks delegates

I am working on a small tool to schedule p4 sync daily at specific times.
In this tool, I want to display the outputs from the P4API while it is running commands.
I can see that the P4API.net has a P4Callbacks class, with several delegates: InfoResultsDelegate, TaggedOutputDelegate, LogMessageDelegate, ErrorDelegate.
My question is: How can I use those, I could not find a single example online of that. A short example code would be amazing !
Note: I am quite a beginner and have never used delegates before.
Answering my own questions by an example. I ended up figuring out by myself, it is a simple event.
Note that this only works with P4Server. My last attempt at getting TaggedOutput from a P4.Connection was unsuccessful, they were never triggered when running a command.
So, here is a code example:
P4Server p4Server = new P4Server(syncPath);
p4Server.TaggedOutputReceived += P4ServerTaggedOutputEvent;
p4Server.ErrorReceived += P4ServerErrorReceived;
bool syncSuccess = false;
try
{
P4Command syncCommand = new P4Command(p4Server, "sync", true, syncPath + "\\...");
P4CommandResult rslt = syncCommand.Run();
syncSuccess=true;
//Here you can read the content of the P4CommandResult
//But it will only be accessible when the command is finished.
}
catch (P4Exception ex) //Will be caught only when the command has completely failed
{
Console.WriteLine("P4Command failed: " + ex.Message);
}
And the two methods, those will be triggered while the sync command is being executed.
private void P4ServerErrorReceived(uint cmdId, int severity, int errorNumber, string data)
{
Console.WriteLine("P4ServerErrorReceived:" + data);
}
private void P4ServerTaggedOutputEvent(uint cmdId, int ObjId, TaggedObject Obj)
{
Console.WriteLine("P4ServerTaggedOutputEvent:" + Obj["clientFile"]);
}

FileSystemWatcher not firing upon text file change and how to get appended lines into panel

I'm after some help or guidance if possible.
I'm trying to monitor a text file in real time and copy the appended text into panel within windows forms.
The text file is being updated via an exe file so it might be few lines appended in quick sessions or nothing for few minutes.
I have tried FileSystemWatcher but it does not seem to work which I cannot understand and also I'm very new to this event handlers etc and still learning in progress :(
private FileSystemWatcher watcher = new FileSystemWatcher();
public async void StandardOutputHandler(object sender, DataReceivedEventArgs outLine)
{
if (outLine.Data != null && !String.IsNullOrWhiteSpace(outLine.Data)) //checks if line coming from CMD is blank or empty
{
// check if cmd output was redirected into a log file
if (outLine.Data.Contains(">>"))
{
BeginInvoke(new MethodInvoker(() =>
{
//get log path and name
string[] commandLine = outLine.Data.Split('>');
this.logFileFullPath = commandLine[3];
this.logFileFullPath = this.logFileFullPath.Replace('"', ' ').Trim();
string[] split = logFileFullPath.Split('\\');
this.logFileName = split[6];
this.path = split[0] + "\\" + split[1] + "\\" + split[2] + "\\" + split[3] + "\\" + split[4] + "\\" + split[5];
//// Create a new FileSystemWatcher and set its properties.
watcher.Path = this.path + "\\";
watcher.Filter = this.logFileName;
//watch for changes to a a log file
watcher.NotifyFilter = (NotifyFilters.LastWrite | NotifyFilters.Size | NotifyFilters.LastAccess | NotifyFilters.CreationTime);
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
// Begin watching.
watcher.EnableRaisingEvents = true;
}));
}
}
// Define the event handlers.
private void OnChanged(object source, FileSystemEventArgs e)
{
MessageBox.Show("Im here");// not showing
//how to copy appended lines into panel??
}
The message box in OnChanged method is not coming up. I have manually amended the file or delete it and create it but the event is not being fired.
I believe this might be related to file being used by another process which in this case is an exe file updating it when necessary. Also, I think, the risk is that I might get only partial text if exe updates the log at the same time as I read the appended lines.
Is there a better way to monitor the text file updates and copy the content onto the panel within GUI application??
UPDATE:
I have moved the code into click event or initial method and it makes no difference. Message box is not appearing
public BatchRun()
{
InitializeComponent();
watcher.Path = "C:\\Test\\Projects\\99999\\Logs";
watcher.Filter = "*.log";
watcher.NotifyFilter = (NotifyFilters.LastWrite | NotifyFilters.Size | NotifyFilters.LastAccess | NotifyFilters.CreationTime);
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;
}
It seems that you only begin watching the file in the call to StandardOutputHandler.
If this method is only called after writing to the file, then the watcher won't notice any changes to the file.
You probably want to have all the code in your MethodInvoker action somewhere it is called when the application starts (or at least when it needs to monitor the file).
Then in your OnChanged method you may have to invoke MessageBox.Show() on the UI thread.

what is best way to leave a groovy script prematurely (except system.exit(0))

what is best way to leave a groovy script prematurely ?
A groovy script reads a row from a given info file then makes some verification work, in case of verification fails (inconsistent data) script needs to leave the flow prematurely . Then system will call the script again to read next row of the same info file
Code example :
read a row
try{
//make some verification here
}catch(Exception e){
logger("exception on something occurred "+e,e)
//here need to leave a groovy script prematurely
}
Just use System.exit(0).
try {
// code
} catch(Exception e) {
logger("exception on something occurred "+e,e)
System.exit(0)
}
You could use the exit status code to indicate what line you had problems with.
A zero value would indicate that everything was OK, and a positive value would be the line number. You could then let your groovy script take the start line as an input parameter.
This is a naive implementation with just a silly exception if a line is empty.
file = new File(args[0])
startLine = args[1].toInteger()
file.withReader { reader ->
reader.eachLine { line, count ->
try {
if (count >= startLine) {
if (line.length() == 0) throw new Exception("error")
println count + ': ' + line
}
} catch (Exception ignore) {
System.exit(count)
}
}
}
I'm pretty sure you can just return from a script.
Simply use return:
read a row
try{
//make some verification here
}catch(Exception e){
logger("exception on something occurred "+e,e)
//here need to leave a groovy script prematurely
return
}
Use return 0
read a row
try{
//make some verification here
}catch(Exception e){
logger("exception on something occurred "+e,e)
return 0;
}

Resources