arclanguage / anarki

Community-managed fork of the Arc dialect of Lisp; for commit privileges submit a pull request.
http://arclanguage.github.io
Other
1.17k stars 160 forks source link

No unvote button #89

Open hjek opened 6 years ago

hjek commented 6 years ago

There's no unvote button after voting for an item. HN has this now, but I can't remember seeing it there before. (I'll keep an eye out to see approximately how long they let you unvote for.)

hjek commented 6 years ago

More info on how unvoting works, in particular for down votes.

matthewwiese commented 6 years ago

I'm interested in giving this feature a shot.

From what I can tell this chunk of code:

(= votejs* "
function byId(id) {
  return document.getElementById(id);
}

function vote(node) {
  var v = node.id.split(/_/);   // {'up', '123'}
  var item = v[1];

  // adjust score
  var score = byId('score_' + item);
  var newscore = parseInt(score.innerHTML) + (v[0] == 'up' ? 1 : -1);
  score.innerHTML = newscore + (newscore == 1 ? ' point' : ' points');

  // hide arrows
  byId('up_'   + item).style.visibility = 'hidden';
  try { byId('down_' + item).style.visibility = 'hidden'; }
  catch(err) {} // ignore

  // ping server
  var ping = new Image();
  ping.src = node.href;

  return false; // cancel browser nav
} ")

Seems to be the Javascript vote logic. Would a rudimentary unvote look something like this?

  // enable unvote
  byId('unvote_' + item).style.visibility = 'visible';
  // readjust score
  etc...

I'm still getting used to the codebase so anybody with more insight into this please do chime in! :smile:

akkartik commented 6 years ago

Sadly, Javascript is not one of my strengths. (Though I'm learning it for $DAY_JOB..)

Most of the code above is for just cosmetic rendering, if I recall correctly. The key is the ping variable which performs a request to the server. So we need to provide a URL to the 'unvote' link that the Arc server can handle and perform an unvote for.

matthewwiese commented 6 years ago

I'm beginning to get a better idea I think...

There are various functions like votelink, vote-url, canvote, and logvote that I need to dig deeper into to better understand -- perhaps a repurposing of canvote into a canunvote, among other things.

A lot more difficult than simply fiddling with some Javascript... :sweat_smile:

hjek commented 6 years ago

On Tue, Mar 06, 2018 at 01:15:11AM +0000, matt wrote:

A lot more difficult than simply fiddling with some Javascript... :sweat_smile:

Voting in Anarki currently works fine w/o JS. It's only used to cancel browser nav.

Previously I posted a link here to what this functionality looks like on HN.

However, there are some open questions as to how unvoting would work on the back end. One, that comes to mind, is that (if I'm not mistaken) not all votes increments the score of an item (or the karma of the posting user), so unvoting should obviously not decrement a score/karma that the vote didn't increment. Otherwise repeated voting and unvoting could eat away score/karma.

akkartik commented 6 years ago

In the backend votes aren't just counted. Instead, each item contains a list of profiles who voted on it, and each profile has a list of (recent) items they voted on. I imagine (though I haven't actually checked) that you just have to rem the appropriate item from both. If it doesn't exist the rem will just do nothing.

hjek commented 6 years ago

On Tue, Mar 06, 2018 at 02:38:41PM -0800, Kartik Agaram wrote:

I imagine (though I haven't actually checked) that you just have to rem the appropriate item from both. If it doesn't exist the rem will just do nothing.

I may be mistaken about this, but I tried faffing about with this a little bit some time ago, and this is how I remember it.

I think it is possible to for someone to cast a vote on a story without that vote incrementing the score. And I don't think it's easy in retrospect to figure out whether a vote has incremented the score; hence the question is: When someone unvotes a story, should a point be subtracted from the score?

A score is not calculated from a list of votes; it is a value that may possibly be incremented when a vote is cast, as can be seen in the use of ++ i!score in the vote-for function.

Therefore I think it may not be enough to just remove the vote from the list(s) of votes, as the score would have to be changed back too, somehow. (At least I think.)

-- Pelle Hjek hjek@member.fsf.org https://news.hjek.tk

akkartik commented 6 years ago

Ah, you're right.

Looking at vote-for, I see that we "always" increment score, but also sometimes increment sockvotes. Then (realscore i) is defined as (- i!score i!sockvotes).

So perhaps an unvote function would need to replicate the logic in vote-for. Decrement score, and sometimes decrement sockvotes.

It's going to be ugly at the start to have all this duplicated code. But once it's working and tested we can think about how to factor out common code.

rocketnia commented 6 years ago

Seems to me if the list of users who voted on something is already stored, the information about whether their vote was considered a sockpuppet vote could be stored alongside it. Then you can decrement sockvotes if the entry you're removing has that note attached to it.

hjek commented 6 years ago

I have taken a shot at unvoting here. I haven't really tested it yet, but it would be nice if anyone would try it out and tell me everything that's wrong with it :beetle:

(I haven't added any JavaScript to make it behave smoothly in the browser yet. Also, it may be worth noting that HN has dropped the JS code to update the score.)

Seems to me if the list of users who voted on something is already stored, the information about whether their vote was considered a sockpuppet vote could be stored alongside it.

I haven't yet touched the format the votes are stored in anywhere. It might be a good idea to remember which votes are sockpupptes, but how? A vote doesn't have an id. And there's not even a vote template. Votes are just scattered information throughout profiles, items and global variables.

And there's no way of deriving karma/score from the votes, because karma/score is just state.

So perhaps an unvote function would need to replicate the logic in vote-for. Decrement score, and sometimes decrement sockvotes.

That's what I've done.

hjek commented 6 years ago

Also, HN's JavaScript code is up for grabs when adding this unvoting stuff. As dang writes:

Re HN's Javascript: you can use/adapt it however you like!

hjek commented 6 years ago

A lot more difficult than simply fiddling with some Javascript... sweat_smile

@matthewwiese, if you're still interested in doing the JavaScript fiddling part, I think now's the time.

hjek commented 6 years ago

Unvoting is working decently now in the Knark fork.

I think I prefer focusing on actually making the new features, so if someone else feels like porting this to Anarki, that would be great.

matthewwiese commented 6 years ago

@hjek Apologies for not seeing your reply sooner! Unfortunately, I don't have the time atm to devote to this, despite what I imagine to be a relatively easy fix.