I was considering sharing the Perl script I had written, but didn't want to clutter up my post about the winners. Someone asked for it in a comment on that post, so I'm sharing it.
I generally write code with lots of comments, so that a year later when the "maintenance coder" (which might be me!) comes to fix something, there'll be a mostly-accurate guide. Now that I've got these concussions, verbose comments are that much more useful -- because now merely "a day later" I've forgotten a lot of what I was doing.
Also, I generally split code into sections, a habit I started way back working in C, and have dragged it forward to Perl, Python, etc. And, another throwback to C, my scripting code generally just has a line like "exit main();" and then all processing happens inside the main() function/subroutine, and it calls out to others. I've also written my own logging module which I have reproduced several times (since the previous one was locked up in the previous job, and I don't steal code like some people steal pets[1]). (Logging module isn't included here, or used -- the script is self-contained.)
Thus, I won't annotate the code any further; I'll just post it below. Oh also, I'll note that I did this in an Ubuntu 16.04.3 VM, running on this Windows 10 laptop. When I went to copy/paste, it "helpfully" added a CR (carriage return; or, an extra blank line) to every line ending. Rather than going through the below and hitting "down, del" 178 times until each line ending was corrected, I just did an "svn up" on the laptop, as I had checked the code in to my personal Subversion repository. Subversion handles the line endings of text files correctly, so once it appeared on the laptop I was able to easily copy/paste, with no line-ending difficulty.
Also, wanted to note that there are many "print" statements throughout the code, so that as I was developing the solution I could see whether things were happening correctly. I left those in, so the actual output of the votees and number of votes, appears after that -- with a line of text indicating the above are the top 50, and the below are the rest.
I use ActiveState's Komodo IDE to edit and run the script while developing it. Excellent Integrated Development Environment! It's commercial, but they also have a free version Komodo Edit, which just edits, doesn't run the script (and I haven't used it, as I bought a personal license for the IDE years ago and have been upgrading every few years -- still on version 9 right now; I think, like Spinal Tap, they've turned it up to 11 :) ).
If you have any questions on anything in the below, post a comment and I'll do my best to clear up any confusion!
#!/usr/bin/perl
=head1 tabulate_votes2.pl
Second script to tabulate votes, to help me with Steemit. This is for the contest: https://steemit.com/life/@libertyteeth/libertyteeth-community-minnow-support-vote-for-up-to-five-of-your-favorite-minnows-50-will-get-a-5-slot-in-my-steemvoter
1. I do a voting contest, people nominate others, and the contest ends.
2. Gather the votes in a text document, with the voter on the first line, then their votes separated by spaces, commas, and "extra text", finally a blank line.
3. Run this script on it.
From my work log, a full description which I'll massage:
---
The script will need several aspects to it:
1. Detect self-votes and eliminate all votes from that account. Also keep a list of these, so it can present it.
2. Verify that the voter, and each voted account, is a valid account and alert me so I can try various changes to see if I can find the account that was intended.
3. If a voter has more than five votes, then replace the earlier ones with the later ones, so there is a maximum of five votes from any voter.
4. Then sort based on number of votes (likely I'll use Perl, and a hash, with the key being the account name, and the value being an integer, starting at 0 and
increment for each vote; then sort on the values in descending order and choose the top 50).
5. Verify each voted account qualifies as a minnow, and set aside any account that's "close" like between 100% and 110%, but no more.
6. Then spit out the list of the top 50, and those who were "close", and I'll finish manually. Also, those who self-voted, because it was the first freaking rule! :)
By "finish manually" I mean that there might have been an account which, when voted on, qualified. I might be able to determine that via steemd.com; or, perhaps, using
steemworld.com or steemnow.com. Alternately, I might just say "congratulations on escaping minnow status during this contest!" We'll see.
---
This script will produce the following output, separated into sections, with one line for each unique account within each section:
Actual votes:
account,number of votes
"Close" accounts:
account,number of votes
Self-voters:
account
Actually, this script now ONLY produces the "actual votes" -- this round, there weren't any self-voters, so don't need to account for that; and, to get the "close"
accounts, I need Python in order to access the STEEM blockchain.
=cut
=head2 ALWAYS USE STRICT AND WARNINGS
=cut
use strict;
use warnings;
=head2 MODULES USED FROM CPAN
=cut
use Getopt::Long;
=head2 MODULES WRITTEN IN-HOUSE
=cut
=head2 VARIABLE DECLARATIONS
=cut
my $vote_file; # file with votes, from the post -- format described above
=head2 SUBROUTINE DECLARATIONS
=cut
sub main();
=head2 MAIN FUNCTION
=cut
exit main();
=head2 SUBROUTINE DEFINITIONS
=cut
=head2 main
Main routine, which tabulates the votes and writes output.
=cut
sub main() {
GetOptions( "vote_file=s" => \$vote_file,
) or die "Error in command line arguments.\n";
die "ERROR: no vote_file specified!\n" if !defined $vote_file;
open FH, "<$vote_file" or die "ERROR: can't open file [$vote_file]!\n";
my @lines = <FH>;
close FH;
my (%voters, %votes, %close, %self);
# The %voters hash: key will be the voter; value will be an array with up to five elements; remove first if adding sixth.
# %votes: key=votee, value=number of votes.
# %close: key=votee, value=number of votes. NOTE: NOT IMPLEMENTING, as I need Python to talk to the STEEM blockchain.
# %self: key=voter, value=array with up to five elements; remove first if adding sixth (these are who they WOULD have voted for, if one of them wasn't a self-vote).
my $voter;
LINE: foreach my $line ( @lines ) {
chomp $line; # remove trailing '\n'
if ( $line eq "" ) {
if ( !defined $voter ) {
# Could be two blank lines between voters' blocks; or, could be a blank line at the beginning of the file.
print "Skipping blank line\n";
next;
}
print "END current voter [$voter]\n\n";
$voter = undef; # saw a blank line while processing; so, we're done processing the current voter.
next;
}
# Okay, we checked for a blank line. Next, what to do when the line's not blank. First, if we're NOT processing a voter,
# then this line is the voter's name, so set it to start processing.
if ( !defined $voter ) {
$voter = $line;
print "BEGIN processing voter [$voter]\n";
next;
}
# If we're here, the line was not empty, and we are processing a voter's votes. So, extract any "@word" from this text, and add them as votees for that voter.
my @votees = split /@/, $line;
shift @votees; # remove the first element, which is "everything before the first '@'"
foreach my $votee ( @votees ) {
$votee =~ s/ .*$//; # remove any space to EOL
$votee =~ s/,$//; # remove any comma at the end of the votee's name
$votee =~ s/\.$//; # remove any period at the end of the votee's name
print " voted for [$votee]\n";
if ( $voter eq $votee ) {
print " SELF-VOTE DETECTED! All votes by [$voter] will be ignored.\n";
delete $voters{$voter};
$self{$voter} = 1;
next LINE; # Stop processing this voter's votes, they voted for themselves.
}
if ( grep( /^$votee$/, @{$voters{$voter}} ) ) {
print " NOTE: already voted for [$votee] so not adding to the array.\n";
next;
}
push @{$voters{$voter}}, $votee;
# At this point, if the voter has voted for more than five votees, remove one (from the front) so that there are only five.
if ( scalar @{$voters{$voter}} > 5 ) {
my $v = shift @{$voters{$voter}};
print " MORE THAN FIVE VOTES, so dropping [$v]\n";
}
}
# FYI, there weren't any self-votes, so that's good! Looks like it processes the vote file (votes.txt) just fine.
# Next step: output the top 50 that were voted for, as well as the rest -- I will look up whether they are "minnow status"
# either manually, or with a Python script -- as it requires Python in order to interact with the STEEM blockchain.
}
# Okay, now we have the %voters hash completely filled out. So, let's process it into the %votes hash.
foreach my $k ( sort keys %voters ) {
foreach my $v ( sort @{$voters{$k}} ) {
$votes{$v}++;
}
}
# Now, do the reverse: make a hash where the key is the number of votes, and the value is an array containing those voted for.
my %votes_by_num;
foreach my $k ( sort keys %votes ) {
push @{$votes_by_num{$votes{$k}}}, $k;
}
# Now we can output it. Walk through %votes_by_num, then walk through the array that is each key's value, printing out the account and
# the number of votes it obtained, as well as a leading count. If the count reaches 50, say "above are the winners".
my $i = 1; # counter, so can print another header once it hits 50
print "Winners:\n";
foreach my $k ( reverse sort { $a <=> $b } keys %votes_by_num ) { # The "{ $a <=> $b }" does a numerical sort; default is alphabetical, which put "51" after "5"...
foreach my $a ( @{$votes_by_num{$k}} ) {
print "$i: $k $a\n";
$i++;
if ( $i eq 51 ) {
print "\n\nBELOW ARE THE REST OF THE VOTING RESULTS:\n";
}
}
}
print "breakpoint here!\n";
exit 0;
}
Enjoy!
[1] -- I haven't followed her TV career, but a very good friend many years ago shared the "Fuck Me, Ray Bradbury" video of hers (also hilarious!), and I looked for others back then and found this one which is ... odd. :)
(And, has a sad explanation of the behavior, towards the end.)
i think your this inicitive have potential to solve a very big problem i want to give thank you for sharing your great work on steemit
Wow, I actually hadn't thought of that! I am considering making this into a service. Thanks!
well though, even in that way it gona helping them to make all that lenthy process to a simple end
While most of the codes in this post isn't all clear to me, (because i've got very limited knowledge on programming), I acknowledge your efforts to add value to this platform in your own unique way.
So i took the "liberty" of making a gif footer image for you... just my little way of saying "Hey, keep it up sir..."
@pangoli, one of the winners of the latest episode of Community Minnow Support you've got started...
Thank you.
Neat, thanks! If I may ask for a slight change -- pan a little lower on the image (i.e., so one of the "orbs" is fully visible, possibly two or one and a half?), and then move the addition up if necessary so it's over the background?
Sure, i'll get to work....
Okay, done...
Nice work dude . Thanks for sharing your codes with us . Have you worked on any other projects on steemit ?
Not a whole lot. There's the link in my profile, to http://libertyteeth.xyz/show-steemit-edits from which you can see all edits to a post or comment.
I also published a "Binance Trading Spreadsheet" there: http://libertyteeth.xyz/uncategorized/binance-trading-spreadsheet/ (had an article here about it as well).
I've dabbled with the blockchain using Python but keep having difficulties connecting to nodes, so stopped. I was writing a script to send me an email when someone makes a new post; I switched to web-scraping when the nodes kept going up and down. It's on hold right now because I'm in the middle of adding the feature "if not emailing to a phone, include the entire web page" and the formatting gets thrown off. I asked (in a post here a few weeks ago I think) if anybody knew how to email a web page using Python, but got no solid answers.
Plus BTC went bearish, so @haejin's posts (with excellent analysis) weren't "jump on this coin now!", so I didn't "need" it as much and haven't touched it in a while.
This one I started in Perl, which is my strongest language. Python is pretty neat but I prefer Perl; I get the solution developed faster with it. I'm sure, with enough experience with Python, that'd change, but that's where it is right now. So I'm very glad to have found @hoffmann's posts with Perl Steemit integration! Had some issues with it yesterday but I think I'll look into it more today, he replied to my comments on his blogs and I think I'm unblocked now.
From feedback on this post, I've decided that I will write a service to help "Steemit users tabulate votes for a contest."
I'll need to make it far more robust than it is now; I'll want it to be able to take the URL to the contest, and then either web scrape or STEEM blockchain scrape, rather than (like I did for this one) have the contest runner copy/paste the page and then "fix it up" like I did. So I'll mostly be starting from scratch, but will be able to reuse a lot of the above.
I'll need database integration as well, and a way for people to provide inputs -- i.e., some contests don't allow self-voting but some do, so that should be a variable; some contests only allow winners to be of a certain size, and those sizes can be calculated differently, so I'll need to provide multiple "size calculations" and then multiple variables within each; and probably more than I can think of, which means I'll need to make a "what would you like to see?" blog post.
In fact, I'll start on that right now. Thanks!
How many years how long have you been coding ?
Thanks for sharing this with us.
Many people will not even bother to read through comments talkless of reacting to them.
You are a role model and you are leading by example
Thank you for your kind words! As the Beatles sang, "We're all doing what we can." :)
well its extremely a decent work a significant number of challenge proprietor was battling with such issue however now with the arrangement given by you it would turn out to be simple for them to choose the champ.
Thanks! I'm making this into a service, you're now the fourth comment here that said I should do so! :)
@magoo-1 always on duty.
Hlw author this guy owner multi ID and always comment by multi ID.This person always try to chest and get your reward.
You can check transations
Wow i can see that a lot of work was put in place as coding arent easy at all. Hmm @libertyteeth you are really for the minnows
well its really a good work many of contest owner was struggling with such problem but now with the solution given by you it would become easy for them to select the winner.
You and @googlee had the same idea, thanks so much! I am now considering making this into a service.
Thing is, it'll take time (a whole lot of precious time), it's gonna take plenty of time, uh oh:
Haha, neat! The first object to "dance" is the clock -- and it does so aligned with the vocal "time"!!!
Ever since I (today) installed the plugin "YouTube ad blocker" -- YouTube has been glitchy, pausing each video about 10 times. It's doing it right now, as I type, and the song is half over! It should have buffered the whole thing by now. Guess they want us to use competitors! http://d.tube
your work is good and i appriciate your this work to help some ones who need it
and also to see this work in coding ,, i am thinkg on other point that if you are doing coding job well and if you are a programers you should make a app on steemit base like esteem but better from esteem which provide us better features and also quick notifications on new feedings and posts as message with a notification tune like other apps or mobile phone msgs
@libertyteeth maybe my question is out of your post but i just ask you to see your coding,, hope if you will do it sure this work will help every one much more
Thanks! I don't know that I'll do a full interface like eSteem or busy.org; however, from two other comments here, I have decided to make this into a service to help others who run contests on Steemit.
Oh my God!!! There actually are coders that practice proper documentation!! You should be considered a national resource.
Oh, and now I have to go grab all of her music, because that was fucking hilarious.
You made me laugh out loud with your last sentence! Here's the other one I referenced -- I haven't heard them all, as I mentioned I didn't follow her TV career, so haven't seen any of her output for years.
Thanks for the coding praise as well!
you are a legend in coding we all knew it ;)
:) Thanks!
Strong people do not put others down ... They make them high ... just as you... Awesome script
Powerful feedback, thank you! I'm turning it into a service to help other Steemit users tabulate their own contests.
Thank you @libertyteeth
@libertyteeth That's Really a Great work .. i appreciate it , I love making scripts with different languages , Makes you think a lot & You can create scripts that make it easier for you to do something Thank you so much for sharing :)
Nice. I do not regret following you. Your post always shows interesting information and adds my insight in writing.
Thank you for posting!
amazing post,,thanks for shating
Definitely some good shating going on.
LOL, because when I was typing out the first few words, I initially wrote "I was considering sharting" and then fixed the typo.
Weird, how the universe keeps rhyming.
Is that what happens when you need a shit but it comes out as a fart?
Yep! Fortunately, it is a rare occurrence... :)
The typo is much more common. :)
To continue "train-of-thought day": it was the single spoken phrase that brought everything into existence, the "uni- verse".
So, funny for me to think that a single phrase could rhyme with itself. And, it probably does, in the "original" Hebrew or Greek, and even more so, in the original language that would probably split me in two to hear it.
Still, neat to be able to hear echoes of the rhyming throughout the imaginary construct we call time.
Wow, you have really done a great work here.
If not for this knowledge, it wouldnt have been easy to pile out names and votes..
You earn my respect @libertyteeth
It is an imperative and generalist programming language. Invented in the early 1970s to rewrite UNIX, C has become one of the most used languages. Many more modern languages like C ++, C #, Java and PHP have aspects of
It is a programming language used in the Linux system, because it is difficult to penetrate Linux, so you can give it commands using the programming language, it is one of the best current systems, it helps protect computers from hacking @liberteyteeth
I am about to complete my computer engg but still I am not perfect in coding it's because in college we just get theorital knowledge about coding.... But your post has cleared my doubs. I wish I had teachers like you who were pro in coding!!
Very interesting. My brother and his family were here yesterday, and he said (about my concussions and my upcoming need for an income) that I might consider teaching.
I am quite good at it. Not sure there's a lot to be made, though. Perhaps I could do some online training. I've been thinking about making videos recently, I've been told I have a face for radio. :)
Tough part though would be making myself available -- it's one thing for me to just write articles; it's another for me to sit around on Discord or something, which I'm not doing (been there once or twice).
Anyway, thanks for the kind words! :)
very important content and fantastic video music. keep it up.
wow very nice post.
wow very nice post
very excellent post
Nice post sir.
Great post sir..your post is so learning and informative..
Thanks for your valuable and informative post........
We can gather a lot of information by your post.
By dint of we can increase our skill that is beneficial for all steemians.
I will always visit your site & wait for your upcoming post.
Thanks ........
wonderful blog sir... you are awesome...👍
Although the above-discussed script is extremely simple, it provides a good basis for learning about more of Perl's capabilities and creating more useful programs.
wow you shared this for free to everyone you have a big heart thanks for sharing this :)
looks like its about that time i need to up my coding skills too
this was really a cool experience to read the post and the coding not as good as you but love to understand thanks bro for sharing
I can say you blindly that you are taking a huge step. Notification on steemit is must be needed right now. Waiting to see it live soon. BTW great peoples don't hurt others. They just take respect from others with their works.