1
votes

I'm attempting to use input received and build a table based on a specific input found (ID#). This input also contains variables that I need to parse and I use those other var's to build a completed data string. In that same file, is a list that the items should be recorded in. Once the file is received and has been completely parsed by the Lua script, it would then send strings back in a particular sequence that is also located within the same file received.

For example:

Input Received:

Log Entries Received:
ID1 - 9:25AM - 10:15AM - Mike Stephens - 2/12/2015 - 111 Dynamo Dr.
ID2 - 8:07AM - 12:20PM - Gary Roberts - 1/23/2015 - 1212 Badger Way
ID3 - 11:46AM - 1:31PM - Trishia Major - 2/10/2015 - 325 March Manor
ID4 - 2:49PM - 3:13PM - Harry Davis - 12/21/2014 - 844 Anapolis Dr.
ID5 - 7:56AM - 8:47AM - Mary Hudson - 1/19/2015 - 9124 Royal Dr.
ID6 - 9:41AM - 4:16PM - Mark Harrison - 1/29/2015 - 583 Connecticut Rd.
ID7 - 10:25AM - 12:45PM - Jennifer Smith - 12/30/2014 - 42 Rodding Rd.
End of Log Entries

Order to be Sent:
ID3 - ID2 - ID5 - ID1 - ID7 - ID4 - ID6
End of Order

Now the ID# is received in chronological order... 1, 2, 3, 4, etc; until all input strings are received. At the end of all of this data received, is another list in which the strings should be handled. This comes in one complete file.

Initially, I thought that it was best to have two separate tables, each built and maintained within their own separate function. The first function would receive the order for the queue, pairing the table's keys with the values (ID#'s) in the order received. This happens in the function below called function iD_Order(log_queue). The second function would use the input data to build the finished strings, found in function string_build(log_input). I want to build a second table, setting the keys of the second table equal to the ID# found within the strings and the values equal to the finished strings themselves.

The disconnect I have would be how to use these two functions together so that when it was time to send the next one in line, it does so based on the queue received. Also, I want to make it so that once the entire queue has been successfully passed, it completely deletes both tables so the process can repeat again from scratch.

Here is what I have so far based on the information, and my thoughts for best approach, I've provided.

function string_build(log_input)  -- takes input and creates strings (don't know how to build table found in this function)
    t_msg = {}
    for iD, time_In, time_Out, usr_Name, date, usr_Addr in input:gmatch("(ID%d)|(.-)|(.-)|(.-)|(.-)|(.-)") do
        finish_Str = "Operator Name: "..usr_Name.." (ID#:"..iD..") on "..date.." signed in at "..time_In.." and signed out at "..time_Out.." at "..usr_Addr.." open house location."
    end
    for k,v in pairs (t_msg) do
        t_msg.iD = finish_Str -- I strongly doubt this is correct????
    end
end

function iD_Order(log_queue) -- takes queue and puts values = order of ID#'s
    t_Queue = {}
    for iD_nmbr in log_queue:match("(ID%d)") do
        for k,v in pairs (t_Queue) do
            table.insert(t_Queue, #t_Queue, iD_nmbr)
        end
    end
end

function log(input) -- main function that receives outside input and sends it to appropriate functions
    local buffer = ""
    input = input:gsub("%s-%s", "|")
    buffer = buffer..input.."|"
    log_input = input:match("Log Entries Received:(.*)End of Log Entries")
    log_queue = input:match("Order to be Sent:(.*)End of Order")
    if log_input then
         string_build(log_input)
         buffer = buffer:sub(#log_input)
    end
    if log_queue then
         iD_Order(log_queue)
         buffer = buffer:sub(#log_queue)
    end
end

Here is where I am unsure what would be the best practice. Being fairly new to programming in general, I am trying to learn the best practice/mindset to strive for. I think that perhaps, having one table rely on another in a completely different function may be bad practice? I'm unsure. But I was thinking of having another function that would grab the table from function iD_Order(log_queue) and the strings created with function string_build(log_input) and select them based on the iD variable may be messy and could cause problems when deleting the tables at the very end.

I think it is best to have the finished strings sent directly into the t_Queue if the key of the t_Queue matched the iD variable in the finished string. But I'm having a hard time figuring out how to do this.

  • Any help in understanding if it is ok to go the route of one or two functions to do this is great.
  • I think it is better to do it all in one function, but can't figure it out. Can I get some assistance in figuring this out?
  • What's the best way of deleting the entire table(s) once the entire table(s) is built and sent back out to another source? These finished strings are sent out to orders that are filled. It can be immediate, it can take hours. But in the end, I want to have the table to be cleared once the final string is sent.

I appreciate all help, input and criticism.

1

1 Answers

1
votes

Your approach seems like it's heading in the right direction. Since your IDs are unique and they are the value you want to use to refer to log entries, it makes sense to use them as the keys for your input table, either as strings ("ID1") or as numbers (1) but numbers are probably a bit nicer. And since the order table is just a sequence of your keys, printing in any order becomes very easy.

A good way to deal with the dependencies between the functions is to define a general format for a log entry. Somewhere down the line you might want to modify the log entries, sort by username etc, so parsing them into tables will pay off with the fields separated.

Separate Input and output operations

separating the input and output is helpful as well, down the line you may have many ways of getting a log entry, and many ways of outputting them, so avoid coupling input and output.

Keep scopes local

It's usually best to use local variables in your functions and return the results so each call doesn't change a global table. If you wanted to parse multiple files this might have caused some unexpected behaviour. And when the function exits the local variables are gone (unless the have been returned), so in the function reorder_log_entries() both the created tables are destroyed when it finishes and you call call it again so you don't need to worry about deleting/emptying the tables. The code below is how i would go about organizing the functionality, but it doesn't read/write to a file.

function parse_order(log_order)
    local order = {} -- make it local to avoid clashes
    for id in log_order:gmatch("ID(%d)") do
        order[#order + 1] = tonumber(id) -- append id to table.
    end
    return order -- {3, 2, 5, 1, 7, 4, 6} in example.
end

function parse_log_entry(entry)
    local ID, time_In, time_Out, usr_Name, date, usr_Addr =
       entry:match("ID(%d) %- (.-) %- (.-) %- (.-) %- (.-) %- (.-)")
    return {id=tonumber(ID), time_in=time_In, time_out=time_Out,
        user_name=usr_Name, date=date, user_addr=usr_Addr}
end

function format_log_entry(entry)
    return "Operator Name: "..entry.user_name
       .." (ID#:"..entry.id..") on "
       ..entry.date.." signed in at "..entry.time_in
       .." and signed out at "..entry.time_out
       .." at "..entry.user_addr.." open house location."
end

input = [[Log Entries Received:
ID1 - 9:25AM - 10:15AM - Mike Stephens - 2/12/2015 - 111 Dynamo Dr.
ID2 - 8:07AM - 12:20PM - Gary Roberts - 1/23/2015 - 1212 Badger Way
ID3 - 11:46AM - 1:31PM - Trishia Major - 2/10/2015 - 325 March Manor
ID4 - 2:49PM - 3:13PM - Harry Davis - 12/21/2014 - 844 Anapolis Dr.
ID5 - 7:56AM - 8:47AM - Mary Hudson - 1/19/2015 - 9124 Royal Dr.
ID6 - 9:41AM - 4:16PM - Mark Harrison - 1/29/2015 - 583 Connecticut Rd.
ID7 - 10:25AM - 12:45PM - Jennifer Smith - 12/30/2014 - 42 Rodding Rd.
End of Log Entries

Order to be Sent:
ID3 - ID2 - ID5 - ID1 - ID7 - ID4 - ID6
End of Order]]


-- read the log entries from the input string
function reorder_log_entries(input)
    local log = {}
    local log_paragraph = input:match("Log Entries Received:(.*)End of Log Entries")
    for line in log_paragraph:gmatch("%s*([^\r\n]+)") do
       entry = parse_log_entry(line)
       log[entry.id] = entry
    end
    local order = parse_order(input:match("Order to be Sent:(.*)End of Order"))
    for _, id in ipairs(order) do
       print(format_log_entry(log[id]))
    end
end