Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"You cannot change your vote ..." is wrong #335

Closed
polyluxus opened this issue Jun 19, 2018 · 20 comments
Closed

"You cannot change your vote ..." is wrong #335

polyluxus opened this issue Jun 19, 2018 · 20 comments
Assignees
Milestone

Comments

@polyluxus
Copy link

polyluxus commented Jun 19, 2018

Installed Version: 2.2.1DEV Environment: Tampermonkey

Current Behaviour

The script locks the vote buttons, if the post was edited longer than 5 minutes ago, giving the following tooltip

You cannot change your vote on posts that were last edited more than 5 minutes ago.

That is incorrect. As explained in What are the limits on how I can cast, change, and retract votes?:

  • In general, once you have voted, you cannot change your vote. There are two exceptions.
    • Exception one: you may change your vote a practically unlimited number of times within a five minutes window from the first vote you cast on that post. Note that after changing your vote ≈60 times, it will also be locked in.
    • Exception two: you may change your vote after every time the post is edited. A new window starts with the first vote you cast after each edit.

It does not matter when the post was edited, the votes remain unlocked until you vote again (and five minutes thereafter).

votes


Steps to reproduce

  1. Go to a post and vote on it
  2. Wait five minutes for the vote to lock
  3. Edit the post
  4. Wait five minutes to trigger the extension lock, see the tool tip
  5. (Disable option "Voting-disableVoteButtons" and change your vote.)

Features Enabled

["Appearance-addAuthorNameToInboxNotifications","Appearance-alignBadgesByClass","Appearance-answerTagsSearch","Appearance-colorAnswerer","Appearance-dragBounty","Appearance-isQuestionHot","Appearance-localTimestamps","Appearance-markEmployees","Appearance-metaChatBlogStackExchangeButton","Appearance-scrollToTop","Appearance-spoilerTip","Appearance-standOutDupeCloseMigrated","Appearance-topAnswers","Appearance-unspoil","Comments-autoShowCommentImages","Comments-commentReplies","Comments-commentShortcuts","Comments-confirmNavigateAway","Comments-copyCommentsLink","Comments-moveBounty","Comments-hiddenCommentsIndicator","Editing-addSBSBtn","Editing-editComment","Editing-editReasonTooltip","Editing-kbdAndBullets","Editing-titleEditDiff","Editing-inlineEditorEverywhere","Editing-downvotedPostsEditAlert","Flags-flagOutcomeTime","Flags-flagPercentages","Flags-flagPercentageBar","Sidebar-hideHireMe","Sidebar-linkedToFrom","Sidebar-hotNetworkQuestionsFiltering","Chat-chatEasyAccess","Chat-replyToOwnChatMessages","Chat-renameChat","Voting-betterCSS","Voting-stickyVoteButtons","Voting-disableVoteButtons","Extras-alwaysShowImageUploadLinkBox","Extras-linkedPostsInline","Extras-parseCrossSiteLinks","Extras-quickAuthorInfo","Extras-shareLinksMarkdown","Extras-sortByBountyAmount","Extras-warnNotLoggedIn","Extras-showMetaReviewCount","Extras-copyCode","Extras-dailyReviewBar","Extras-showQuestionStateInSuggestedEditReviewQueue"]
@shu8 shu8 self-assigned this Jun 19, 2018
@shu8 shu8 added this to the 2.3.0 milestone Jun 19, 2018
@shu8
Copy link
Member

shu8 commented Jun 19, 2018

@polyluxus thanks, looks like I overlooked that when I added the feature! Sorry! I'll get it fixed ASAP

@shu8
Copy link
Member

shu8 commented Jun 19, 2018

Looking into this, I can't see a way to find a user's vote time with the API.

I might ask on Stack Apps if I can't see find a way, but if there isn't I might not be able to fix this :/

@GaurangTandon
Copy link

GaurangTandon commented Jun 20, 2018

The problem is apparently right after this comment:

//Grays out votes on posts which haven't been edited in the last 5 minutes

doesn't seem to be a bug though, as the script works as intended :P (jk)

Anyway, the simple fix seems to be simply (REMOVED - see better fix below)

@GaurangTandon
Copy link

Or perhaps here's a better method that works across user sessions, by using localStorage to track timestamps:

  1. construct voteTimestamp hashmap with structure as {post_id : timestamp}. Store it in localStorage. This is intended to keep track of vote buttons within five minute editing window across page loads.
  2. construct a local hashmap (say voteTimeouts) with structure as {post_id: timeouts} to keep track of currently running timeouts
  3. on page load, go through every vote button that has a pre-casted vote, and look up its associated post id in the hashmap.
    • If the entry is present in the hashmap, that means that vote button belongs to the five minute editing window. in such case, setTimeout for the remaining time the user has (Date.now() - timestamp). add the timeout to voteTimeouts. if that vote button is used again, clearTimeout and reset it as per condition.
    • otherwise, the vote button is past the five minute editing window and now should be disabled
  4. once page is loaded, watch $(document).on("sox-vote") (might have to create it if it doesn't exist). for every event, store its timestamp and timeout in the respective hashmaps, and proceed as in 3.

This is perfect, except that there's absolutely no way to tell if the post was edited after the vote button is past the five minute edit window. The only way to do so is to have the voteTimestamp hashmap stored permanently.

What are the implications of storing a timestamp hashmap permanently?

A user of SOX is generally supposed to be a very active SE user. Considering that, their voting activity (https://SITE.stackexchange.com/users/ID/NAME?tab=topactivity) would easily be around 4000-5000 votes on every SE site they are proactive in.

post_id is generally 5 to 8 chars long depending on SE site. Any timestamp will continue to be 13 chars long until we die. That is an overhead of nearly 20 chars per vote. Or 100k chars overall for one SE site. Add more SE sites in and you get the picture.

I think if there's a feature advertised, then it should work as intended, so if the overhead is required, it has to be done. On Chrome 67, the max size on localStorage is 5200000 characters. So, storage shouldn't be much of an issue. Still, I believe a helpful warning for the users who enable this feature would suffice.


Sorry, for the really long description though, I was just trying to make it as comprehensive as possible. I'll just let it be here for some more time. If no one else comes up with better ideas, I'll try implement this then.

@shu8
Copy link
Member

shu8 commented Jun 20, 2018

@GaurangTandon nice idea! Instead of localStorage it could probably be another GM value so it doesn't get deleted as easily.

However, I think a much simpler (not sure about clean...) method would be to just scrape the votes page by GETting https://meta.stackexchange.com/users/current?tab=votes&sort=upvote. Chances of a user upvoting 30 posts (the amount listed on the page) in 5 minutes are slim, and even if they do, the next page can be fetched too. The page could be requested just once, and a list of the post IDs on the current page can be found and compared to

I think it will be simpler because we won't need to store (possibly quite a bit) extra data and it wouldn't require us to log votes ourselves and manage when to delete them. It also has the advantage that we won't need to store stuff like which site the vote was on

@GaurangTandon
Copy link

GaurangTandon commented Jun 21, 2018

@shu8 nice! That page has the timestamp values in the title attribute of .date-brick, so that isn't an issue. Also, the point about "we won't need to store stuff like which site the vote was on" is spot on.

I get it that this won't require us to store timestamps anywhere, but then, would you fetch that page every time I load any SE question page? I believe if I am concerned about storage, I am also equally concerned about bandwidth, and considering that I browse SE for hours daily, that page really looks expensive :O

You would only want to fetch it once per day for every site imo. But in that case as well, you'd still need to store that fetched value. So, the problem that you were trying to tackle (not using storage) remains.

That brings me to my more important point, I miscalculated the size of voteTimestamp hashmap Yeah, the actual size required for voteTimestamp would not even be 800 chars for one site at maximum usage, or just 0.8KB. The reason is that voteTimestamp stores post_ids for those posts which were voted upon in the past five minutes only. Once that time period is over, or the vote is cancelled by the user, we can delete the entry for that post_id from voteTimestamp.

Considering that rarely anyone goes on a forty vote ("Vox Populi") sprint in five minutes, the average size of voteTimestamp is expected to be around 20 * 10 = 200 chars.

Thoughts?

@polyluxus
Copy link
Author

@shu8 I'm not sure I follow here, I don't see how that page can be of any help. I am not a programmer, so I might not get the full picture here.

This is going to be a little pseudo-cody, I hope you understand. From what I see, you would have to

  1. determine when the post was edited,
  2. you would have to scrape the votes page until that timestamp,
    • if you don't find a vote during that time, the buttons should be unlocked,
    • if you do find a vote:
      • check if the vote is older than five minutes -> locked
      • the vote was within the last five minutes -> unlocked

Given that you sometimes return to a post a year ago and see it changed quite a bit, and then you consider to change your vote (usually going from down to up, or at least remove the vote) I guess that produces quite a bit of overhead.

Then again I have not crawled through any code, so I don't really know anything.

@GaurangTandon
Copy link

GaurangTandon commented Jun 21, 2018

@polyluxus

I'm not sure I follow here, I don't see how that page can be of any help.

Actually, there's a bit of a trick here. At first, I too found it a bit counter-intuitive. But, press F12. Press Ctrl+F in the DevTools Elements Panel. Type .date_brick and it will focus on to the first vote. Then, you'll notice that its title attribute has the exact timestamp ;)

image

@shu8
Copy link
Member

shu8 commented Jun 22, 2018

Sorry, I forgot to actually mention that!

@GaurangTandon sure, your method would use less bandwidth, so I think its worth trying :)

I have asked on Stack Apps though to see if it is possible to get the vote time, so we could maybe wait till I get a response?

@polyluxus
Copy link
Author

@GaurangTandon

Type .date_brick and it will focus on to the first vote.

Exactly, it'll give you the timestamp of the votes, starting with the most recent first. It will not give you the time stamp of the vote you are actually interested in, at least not in an iffy. You'll still have to find that vote in the entire history up to the point when the post was last edited, to determine whether the voting is locked or not.
If you revisit a post you have voted on more than a year ago, and you now notice that an edit has substantially changed it, and you would like to change your vote, you are able to. In that case you'll have to travel back quite a few pages. I see no handy way of doing that in a time frame that actually makes sense.

The last five minutes of the voting history are actually the least important ones. The extension doesn't really need to do anything. It is any vote that was cast before that, but after the last edit, that must trigger the locking of the buttons.

@shu8 Care to share a link of the question?

@GaurangTandon
Copy link

You'll still have to find that vote in the entire history up to the point when the post was last edited

Ah I see what you mean! That's indeed true.

@polyluxus This is the question. Afaict, this approach is very complicated. So, I will build a working model of my approach via the voteTimestamps hashmap, and then share here by tomorrow ASAP.

@shu8
Copy link
Member

shu8 commented Jun 23, 2018

@polyluxus You're right! I overlooked that part!

@GaurangTandon it does look unnecessarily complicated so your idea would be perfect!

@GaurangTandon
Copy link

I'm afraid, but after having written nearly a hundred and twenty lines of code for enabling everything, I realized that my implementation was missing the most crucial point - which @polyluxus had just elaborated. I have no way to tell if the vote - that was cast more than five minutes ago - was cast before or after the post was edited.

Therefore, the fetch mechanism is the way to go for now. However, that should be coupled with the localStorage mechanism, to cache pre-fetched values.

That said though, this also brings us to the point that we might have to fetch gazillions of vote-pages before we finally arrive at the two year old (say) post we are interested in, as @polyluxus has earlier said.

So, at such a high cost, I am not sure if this a feature even worth having, unless we figure out a better way to do it. Thoughts?

@shu8
Copy link
Member

shu8 commented Jun 25, 2018

@GaurangTandon urgh. I see what you mean now :/

I'm struggling to think of a better solution, and I think you're right in saying more than a few fetches is too much for just this feature.

I'm going to leave this open for a while in case we manage to come up with something, but if we don't do you have any thoughts on whether we should just change this back to the feature where your own posts and deleted posts were grayed out, or just not do anything on posts that have had an edit at all, but still work for non-edited posts?

@GaurangTandon
Copy link

GaurangTandon commented Jun 25, 2018

@shu8 I would advise against this because:

  1. it would be an inconsistent behavior. If I find my votes locked on some posts, and not locked on others (when it should be), that'd be a weird user experience for me. Better make it correctly on all posts, or not work on any.
  2. I don't come across deleted posts/own posts as often as I come across edited posts by other people. So, the feature wouldn't work in the main place it's supposed to work :(

@polyluxus thoughts?

@shu8
Copy link
Member

shu8 commented Jun 26, 2018

@GaurangTandon you're right, that would end up being confusing :/

I think we'll just remove this feature then?

@GaurangTandon
Copy link

"I think we'll just remove this feature then?" yep, pretty much what I'm thinking as well.

@polyluxus
Copy link
Author

@shu8 I would appreciate if it would grey out voting buttons on my own posts. I do come across them quite frequently, and it helps me realise that. But maybe it would be better to add that as a new feature, while deleting the old one to avoid confusion.

@shu8
Copy link
Member

shu8 commented Jun 27, 2018

@polyluxus No problem, I'll remove this feature and rename it so it'll work like it used to (own/deleted posts) :)

shu8 added a commit that referenced this issue Jun 28, 2018
@shu8
Copy link
Member

shu8 commented Jun 28, 2018

@polyluxus done in dev v2.2.5 :) You shouldn't need to change any settings, I've just updated the description.

Sorry we couldn't get the other part to work, but it would have been a lot of work to do for such a small feature! :/

@shu8 shu8 added the rejected label Jun 28, 2018
@shu8 shu8 closed this as completed Jun 28, 2018
shu8 added a commit that referenced this issue Sep 2, 2018
* new dev

* #305

* #307

* #310

* #310

* Better fix for #310

The old fix placed the SOX button to the right of the username, but the username only shows up in the top bar if you're logged in. This meant the SOX button would be absent if you were logged out. This new code should fix that.

* #310

* #309, #313

* #311, #312

* #256

* #319, #317, #316

* #256

* #318

* #294 deprecate enhanced editor

* #308, other small fixes

* #320

* minor fixes (#324)

change scroll top top feature JSON info

* fixes #329 (#330)

also reduces jQuery dependency

* v2.1.4 DEV before push to master

also adds #326

* v2.2.0

* inital DEV push

* update readme to state GM not supported; #306

* reduce dependency on `hotkeys`+minor details (#333)

* #334 fixed

* #334

* #334

* #338

* #335, #338

* Micro optimizations (#336)

* update source link

* micro optimizations

- converted jQuery .not to CSS selector for faster perf (https://stackoverflow.com/questions/8845811/performance-differences-between-using-not-and-not-selectors)
- introduced a separate function to eliminate thrice-repeated (!) code, to keep it DRY

* fixes some issues (#339)

described in #338 (comment)

* fixes #338

* fixes #338 (#340)

1. used addEventListener instead of onload
2. descriptive names (`reader`)
3. optimized extraction of the image URL from the `data`
4. made all declarations `var` and moved them into one place for consistency
5. shortened the POST url to simply `'/upload/image?https=true',` ;P

* #322 implemented

* Sticky property

* Update sox.user.js

* Updating button colors

The main SE buttons use a lighter color than the SOX buttons

* Update sox.css

* Minor fixes

Patched a problem with vote buttons, and fixed the color of the notify on edit button

* Update sox.user.js

* minor changes/fixes

* #341 temporary fix

* Updated mod diamond icon

Updated to the icon, to match the one used by the new topbar

* Updated diamond icon

* Updated mod diamond

* improvements in colorAnswerer (#344)

* improvements in colorAnswerer
1. constant variables+cache answeredID
2. reduce jQuery dependency+shorter a[href] selector via user ID
3. change coloration

* optimization: use filters throughout (#345)

reduces bandwidth consumption

* fixes a few features; adds CSS

Fixes moveBounty, dragBounty, copyCommentsLink.
Adds class for colorAnswerer.
Updates jQuery

* fixes quickAuthorInfo fontawesome icon

* fix a few of #308

* Major improvements in code extensibility, reduced API usage, eliminate redundancy, etc. (#348)

* fixes various bugs mentioned in #348

* fixes standOutDupeCloseMigrated for search pages

* remove unwanted console logs

* #347, various minor tweaks

* fixes small bug in parseCrossSiteLinks

e.g. on this comment: https://meta.stackoverflow.com/questions/370902/i-need-a-lot-of-help-to-write-a-query-for-the-stack-exchange-data-explorer-sh?cb=1#comment608548_370902

* Fixed Meta SE's chat link

Added a / to the end of Meta SE's if statement to fix it. Also replaced "discuss" with "meta" for Area 51 (to match the new URL for Area 51 Discussions), shortened a bit of code, and added some comments

* Fixed Meta SE links

* Changed topbar z-index

Changed the fixed topbar's z-index to match the one on SO, in order to prevent elements like the usercard (z-index: 1000) from covering it

* Made it clearer what the checkbox does

* Many fixes to dialog buttons

Fixes many of the bugs from #308

* Many fixes to dialog buttons

Fixes many of the bugs from #308

* Many fixes to dialog buttons

Fixes many of the bugs from #308

* Many fixes to dialog buttons

Fixes many of the bugs from #308

* Fixed Area 51 Discussions bug

* #348 minor tweak

* fix (#350)

...for answerer ID 13 also matching commenter ids beginning with 13 (1345, 13555, etc.)

* #352, #353 remove yahoo YQL use

* #352

* PR/351 (#355)

* update getQuestionTags

* provide immediate response to user

* minor changes

* #325: remove rangyInputs dependency (#354)

* bump version number

* remove downvotedPostsEditAlert; remove rangyinputs `require`; implement mini changelog in dialog

* install stale and no-response bots

* #356 added, minor bug fix

* start #349, start to move to es6

* onlyShowCommentActionsOnHover bug fix

* #357

* deprecate fixedTopbar feature for #349

* add showTagWikiLinkOnTagPopup feature

* #359 fixed

* #358 fixed

* fixes #360

* fixes for #361

* #361 changes

* v2.3.0 final
shu8 added a commit that referenced this issue Feb 3, 2019
* new dev

* #305

* #307

* #310

* #310

* Better fix for #310

The old fix placed the SOX button to the right of the username, but the username only shows up in the top bar if you're logged in. This meant the SOX button would be absent if you were logged out. This new code should fix that.

* #310

* #309, #313

* #311, #312

* #256

* #319, #317, #316

* #256

* #318

* #294 deprecate enhanced editor

* #308, other small fixes

* #320

* minor fixes (#324)

change scroll top top feature JSON info

* fixes #329 (#330)

also reduces jQuery dependency

* v2.1.4 DEV before push to master

also adds #326

* v2.2.0

* inital DEV push

* update readme to state GM not supported; #306

* reduce dependency on `hotkeys`+minor details (#333)

* #334 fixed

* #334

* #334

* #338

* #335, #338

* Micro optimizations (#336)

* update source link

* micro optimizations

- converted jQuery .not to CSS selector for faster perf (https://stackoverflow.com/questions/8845811/performance-differences-between-using-not-and-not-selectors)
- introduced a separate function to eliminate thrice-repeated (!) code, to keep it DRY

* fixes some issues (#339)

described in #338 (comment)

* fixes #338

* fixes #338 (#340)

1. used addEventListener instead of onload
2. descriptive names (`reader`)
3. optimized extraction of the image URL from the `data`
4. made all declarations `var` and moved them into one place for consistency
5. shortened the POST url to simply `'/upload/image?https=true',` ;P

* #322 implemented

* Sticky property

* Update sox.user.js

* Updating button colors

The main SE buttons use a lighter color than the SOX buttons

* Update sox.css

* Minor fixes

Patched a problem with vote buttons, and fixed the color of the notify on edit button

* Update sox.user.js

* minor changes/fixes

* #341 temporary fix

* Updated mod diamond icon

Updated to the icon, to match the one used by the new topbar

* Updated diamond icon

* Updated mod diamond

* improvements in colorAnswerer (#344)

* improvements in colorAnswerer
1. constant variables+cache answeredID
2. reduce jQuery dependency+shorter a[href] selector via user ID
3. change coloration

* optimization: use filters throughout (#345)

reduces bandwidth consumption

* fixes a few features; adds CSS

Fixes moveBounty, dragBounty, copyCommentsLink.
Adds class for colorAnswerer.
Updates jQuery

* fixes quickAuthorInfo fontawesome icon

* fix a few of #308

* Major improvements in code extensibility, reduced API usage, eliminate redundancy, etc. (#348)

* fixes various bugs mentioned in #348

* fixes standOutDupeCloseMigrated for search pages

* remove unwanted console logs

* #347, various minor tweaks

* fixes small bug in parseCrossSiteLinks

e.g. on this comment: https://meta.stackoverflow.com/questions/370902/i-need-a-lot-of-help-to-write-a-query-for-the-stack-exchange-data-explorer-sh?cb=1#comment608548_370902

* Fixed Meta SE's chat link

Added a / to the end of Meta SE's if statement to fix it. Also replaced "discuss" with "meta" for Area 51 (to match the new URL for Area 51 Discussions), shortened a bit of code, and added some comments

* Fixed Meta SE links

* Changed topbar z-index

Changed the fixed topbar's z-index to match the one on SO, in order to prevent elements like the usercard (z-index: 1000) from covering it

* Made it clearer what the checkbox does

* Many fixes to dialog buttons

Fixes many of the bugs from #308

* Many fixes to dialog buttons

Fixes many of the bugs from #308

* Many fixes to dialog buttons

Fixes many of the bugs from #308

* Many fixes to dialog buttons

Fixes many of the bugs from #308

* Fixed Area 51 Discussions bug

* #348 minor tweak

* fix (#350)

...for answerer ID 13 also matching commenter ids beginning with 13 (1345, 13555, etc.)

* #352, #353 remove yahoo YQL use

* #352

* PR/351 (#355)

* update getQuestionTags

* provide immediate response to user

* minor changes

* #325: remove rangyInputs dependency (#354)

* bump version number

* remove downvotedPostsEditAlert; remove rangyinputs `require`; implement mini changelog in dialog

* install stale and no-response bots

* #356 added, minor bug fix

* start #349, start to move to es6

* onlyShowCommentActionsOnHover bug fix

* #357

* deprecate fixedTopbar feature for #349

* add showTagWikiLinkOnTagPopup feature

* #359 fixed

* #358 fixed

* fixes #360

* fixes for #361

* #361 changes

* v2.3.0 final

* 2.3.0 DEV

* fix for #363

* implemented 'feature packs' in settings dialog

* debugging for #363, fixes #364

* #363 debugging

* fix for #363

* #361 implemented (access token no longer mandatory); minor code cleanup

* #365

* fix #368

* Add #315

* fix #366

* start to use linting

* fix #372

* add #370

* clean up code

* implement #374

* fix #373

* add #370; deprecate pasteImagesDirectly

* #374 replace 'help' instead of prepend new link

* change indentation to 2 spaces

* lint

* implement #296

* implements #376 (linkify meta diamond dialog title)

* fix #375 (topAnswers post score not being found)

* improve customMagicLinks feature -- add button to help menu on all pages

* fix sticky vote buttons feature

* keep new meta posts under diamond even after clicking (#378)

* editComment improve design, add more defaults (#377)

* fix better css feature

* editComment: make dialog delete button smaller

* improve editComment for #377; allow editing; new setting storage format

* add delay to comment features for links to deleted comments #379

* bump to v2.4.0

* Remove accidental letter introduced into file

* Bump installation link version numbers

* Lint
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants