Community discussions

MikroTik App
 
User avatar
worm
just joined
Topic Author
Posts: 9
Joined: Sun Jul 09, 2023 3:48 pm

I want to sort the speed measurement results from high to low, but I find it impossible to do so no matter what!

Mon Mar 17, 2025 2:51 pm

{
    /file print file=Log.txt;
    :delay 2;
    /file set Log.txt contents="";

    # Array to store all speed test results
    :local results "";

    :for i from=1 to=3 do={
        /interface pppoe-client enable ("pppoe-out".$i);
        /interface pppoe-client set ("pppoe-out".$i) comment="Waiting for results...";
        :delay 5;

        :local txAvg 0;
        /tool bandwidth-test 111.222.333.444 duration=5s direction=transmit protocol=tcp user=admin do={
            :set txAvg ($"tx-10-second-average"/1000);
        }

        :local currentComment [/interface pppoe-client get ("pppoe-out".$i) password];
        :local newComment ($currentComment." | Upload: ".($txAvg / 1000)." Mbps");
        /interface pppoe-client set ("pppoe-out".$i) comment=$newComment;

        :if ([:len $results] > 0) do={
            :set results ($results . "\n" . $newComment);
        } else={
            :set results $newComment;
        }
        /interface pppoe-client disable ("pppoe-out".$i);
    }

    # Sort results by speed in descending order
    :local sortedResults "";
    :log info "Starting sorting process.";

    # Debug: Print the content of results before sorting
    :log info ("Results before sorting: ".$results);

    :local lines [:toarray $results];
    :log info ("Total lines to sort: ". [:len $lines]);

    # Debug: Print the lines array to verify splitting
    :local linesDebug "";
    :foreach line in=$lines do={
        :set linesDebug ($linesDebug . ", " . $line);
    }
    :log info ("Lines array: " . [:pick $linesDebug 2 [:len $linesDebug]]);

    :foreach line in=$lines do={
        :if ([:len $line] > 0) do={
            :local speed 0;
            :local uploadPos [:find $line "Upload: "];
            :local mbpsPos [:find $line " Mbps"];
            :log info ("Found 'Upload: ' at position: ".$uploadPos.", 'Mbps' at position: ".$mbpsPos);

            # Extract speed value
            :if (($uploadPos != nil) && ($mbpsPos != nil) && ($mbpsPos > $uploadPos)) do={
                :local speedStr [:pick $line ($uploadPos + 8) $mbpsPos];
                :set speed [:tonum $speedStr];
                :log info ("Extracted speed value: ".$speedStr." Mbps (converted to number: ".$speed.")");
            }

            # Insertion sort logic
            :local inserted false;
            :local tempResults [:toarray $sortedResults];
            :local newSortedResults "";

            :foreach sortedLine in=$tempResults do={
                :if ([:len $sortedLine] > 0) do={
                    :local sortedSpeed 0;
                    :local sortedUploadPos [:find $sortedLine "Upload: "];
                    :local sortedMbpsPos [:find $sortedLine " Mbps"];

                    # Extract speed value from sorted line
                    :if (($sortedUploadPos != nil) && ($sortedMbpsPos != nil) && ($sortedMbpsPos > $sortedUploadPos)) do={
                        :local sortedSpeedStr [:pick $sortedLine ($sortedUploadPos + 8) $sortedMbpsPos];
                        :set sortedSpeed [:tonum $sortedSpeedStr];
                    }

                    # If current speed is greater than sorted speed and not inserted, insert current line
                    :if ($speed > $sortedSpeed && !$inserted) do={
                        :set newSortedResults ($newSortedResults . "\n" . $line);
                        :set inserted true;
                        :log info ("Inserted line: ".$line." (speed: ".$speed." Mbps) into sorted results.");
                    }
                    # Add sorted line
                    :set newSortedResults ($newSortedResults . "\n" . $sortedLine);
                }
            }

            # If not inserted, append current line to the end
            :if (!$inserted) do={
                :if ([:len $newSortedResults] > 0) do={
                    :set newSortedResults ($newSortedResults . "\n" . $line);
                } else={
                    :set newSortedResults $line;
                }
                :log info ("Appended line: ".$line." (speed: ".$speed." Mbps) to the end of sorted results.");
            }

            # Update sorted results
            :set sortedResults $newSortedResults;
            :log info ("Updated sorted results: ".$sortedResults);
        }
    }

    /file set Log.txt contents=$sortedResults;
}
The above code was generated by combining AI and modified by oneself, but the result still cannot be sorted properly. Please consult the expert~The result of the program running is:
2310138 | Upload: 32 Mbps
2310517 | Upload: 48 Mbps
2226923 | Upload: 81 Mbps
And the result I want is:
2226923 | Upload: 81 Mbps
2310517 | Upload: 48 Mbps
2310138 | Upload: 32 Mbps
The ROS version I am using is 6.49.18. Can't version 6. x perform such complex operations?
 
A9691
Frequent Visitor
Frequent Visitor
Posts: 55
Joined: Sat May 14, 2016 10:58 am

Re: I want to sort the speed measurement results from high to low, but I find it impossible to do so no matter what!

Fri Mar 28, 2025 8:52 am

AI has no idea about Ros scripting. Not even the basics.

I suggest you use the built-in sorting of dictionary arrays:
:global l ({})
:set ($l->"c") "three"
:set ($l->"a") "one"
:set ($l->"b") "two"
:foreach k,v in=$l do={:put ("$k:$v")}
Output:
a:one
b:two
c:three
What you have to do is:
- get the speed of an interface, ($speed)
- subtract it from a big enough number so that subtracting does not result in decreasing the number of digits ( something like :set speed (99999 - $speed) )
- collect data into a dictionary array (for example :set ($l->[:tostr $speed]) $interfacename ).

The result will be an array sorted by speed string, lower to higher. If you

Note: it i important to use string, otherwise you'll end up with a huge, number indexed array with lots of empty items.
Don NOT use "$speed" because:
[admin@MikroTik] > :global n 10       
[admin@MikroTik] > :put [:typeof "$n"]
num
[admin@MikroTik] >