PDA

View Full Version : Two different variables somehow sharing the same values



Tgo01
10-01-2016, 11:56 PM
I'm at a complete loss here. For my Dreavening events I have two different Hashes; one keeps track of how many times each person has attended a Dreavening, and the second variable keeps track of how many times they have attended a Dreavening for the current lottery I am holding.

The two Hashes started keeping track at different times so they should have different values for each person yet somehow the Hashes have become equal to one another and instead of adding 1 to each Hash value for every Dreavening the person attends it ends up adding 2 and the Hashes end up being equal to each other.

I stared at the code until my eyes bled (not literally) and could not figure out what the problem was. Finally I put a bunch of echos everywhere throughout the code to see exactly when the problem occurs and I have narrowed down where the problem happens but I still have no idea why this would be happening.

I feel like it's something simple I'm missing but I still don't see it.

The relevant code:



$pre_total_attendance = CharSettings['total_attendance'] unless $pre_total_attendance
$pre_total_lottery_attendance = CharSettings['current_lottery_attendance'] unless $pre_total_lottery_attendance
GameObj.pcs.each{|pc|
temp_attendance_value = nil
if $pre_total_attendance.include?(pc.noun)
temp_attendance_value = $pre_total_attendance.fetch(pc.noun)
CharSettings['total_attendance'].store(pc.noun, (temp_attendance_value + 1))
if $total_dreavenings
if CharSettings['total_attendance'].fetch(pc.noun) > $total_dreavenings
CharSettings['total_attendance'].store(pc.noun, $total_dreavenings)
end
end
else
CharSettings['total_attendance'].store(pc.noun, 1)
end
temp_attendance_value = nil
if $pre_total_lottery_attendance.include?(pc.noun)
##########PROBLEM HAPPENS BETWEEN HERE##########
temp_attendance_value = $pre_total_lottery_attendance.fetch(pc.noun)
CharSettings['current_lottery_attendance'].store(pc.noun, (temp_attendance_value + 1))
##########AND HERE##########
else
CharSettings['current_lottery_attendance'].store(pc.noun, 1)
end
}


So the values for everyone in CharSettings['total_attendance'] Hash go up by 1 like they should and they stay there until after the part I list in the code here then suddenly they go up by 1 again, yet I don't see how this is possible because two totally different Hashes are having their value increase by 1. Am I wrong here? Am I going crazy?

I've looked all over the code and I don't see anywhere where I have accidentally made the two Hashes equal to one another or anything of the sort, yet they are now equal to one another.

Is it because of the names of the Hashes somehow?

Strange thing is I've copied over this bit of code to a totally new script and kept all of the names the same and never saw this problem.

Tgo01
10-02-2016, 03:16 AM
I tried changing the names of the variables to see if this for some reason was affecting anything and it didn't solve the problem.

Next time I'll try commenting out the CharSettings['current_lottery_attendance'].store(pc.noun, (temp_attendance_value + 1)) line to ensure that is the problem, which I'm pretty sure it is.

But I don't see how. How is increasing this value by one increasing the other Hash's values by one?

BigWorm
10-02-2016, 03:53 AM
So I think it is unlikely that this is actually the problematic code. Show me how you initialize the hashes. I bet you are unwittingly reusing the same value for every initialization. This results in every key pointing to the same object.

I think that this might also be possible if you misuse Hash#default but only crazy people use that.

That said, why are you using Hash#store? I don't know of any reason not to use hash[key] = value which is so much more idiomatic. I actually had to look up Hash#store in the docs (https://ruby-doc.org/core-2.2.0/Hash.html#method-i-store) because I never see that in the wild.

Tgo01
10-02-2016, 04:18 AM
So I think it is unlikely that this is actually the problematic code. Show me how you initialize the hashes. I bet you are unwittingly reusing the same value for every initialization. This results in every key pointing to the same object.

Same way I always initialize hashes, Hash.new.

Which granted might be wrong I suppose :p

Other than the echos and what I have already posted, here is every instance of both Hashes being used in the script:

CharSettings['everyone_att'] = Hash.new unless CharSettings['everyone_att'] (granted this line isn't even needed anymore since once the Hash has a value it doesn't do anything. I just keep it around because reasons.)
$total_attendance = CharSettings['everyone_att']


CharSettings['everyone_lottery_att'] = Hash.new unless CharSettings['everyone_lottery_att']
$current_lottery_attendance = CharSettings['everyone_lottery_att']

This is with the name changes of course.


That said, why are you using Hash#store? I don't know of any reason not to use hash[key] = value which is so much more idiomatic. I actually had to look up Hash#store in the docs (https://ruby-doc.org/core-2.2.0/Hash.html#method-i-store) because I never see that in the wild.

I teach myself Ruby as I go along. When I need to learn how to do something I look it up on the internet and the first answer I find that works I go with, just so happens .store was the first thing I found that worked so I kept doing it.

Tgo01
10-02-2016, 04:23 AM
I want to say it's something to do with the global variables I have tied to them, but I can't think of what.

Tillmen
10-02-2016, 08:05 AM
I think the two hashes must be the same. If at any point this script had:

CharSettings['total_attendance'] = CharSettings['current_lottery_attendance']

or this or any other script had:

$pre_total_attendance = $pre_total_lottery_attendance

or the reverse or something similar, then you only have one hash with four ways to access it. This code could have just been a typo that you removed long ago, but if it was saved in CharSettings as one hash with two ways to access it, that's the way it'll be loaded every time. You can check to see if this is the case by adding:

echo CharSettings['total_attendance'].object_id
echo CharSettings['current_lottery_attendance'].object_id

to the script and see if they have the same id. If they do, you're going to have to recreate one of them with Hash.new.

Also, the code you posted could be replaced with this:

$pre_total_attendance ||= CharSettings['total_attendance']
$pre_total_lottery_attendance ||= CharSettings['current_lottery_attendance']
GameObj.pcs.each{ |pc|
CharSettings['total_attendance'][pc.noun] = CharSettings['total_attendance'][pc.noun].to_i + 1
if $total_dreavenings
CharSettings['total_attendance'][pc.noun] = [CharSettings['total_attendance'][pc.noun], $total_dreavenings].min
end
CharSettings['current_lottery_attendance'][pc.noun] = CharSettings['current_lottery_attendance'][pc.noun].to_i + 1
}

And the first two lines are only needed if you want another script or hook to be able to access those settings.

Tgo01
10-02-2016, 04:04 PM
echo CharSettings['total_attendance'].object_id
echo CharSettings['current_lottery_attendance'].object_id


This was certainly the problem. Thank you. This was driving me bananas.



Also, the code you posted could be replaced with this:

$pre_total_attendance ||= CharSettings['total_attendance']
$pre_total_lottery_attendance ||= CharSettings['current_lottery_attendance']
GameObj.pcs.each{ |pc|
CharSettings['total_attendance'][pc.noun] = CharSettings['total_attendance'][pc.noun].to_i + 1
if $total_dreavenings
CharSettings['total_attendance'][pc.noun] = [CharSettings['total_attendance'][pc.noun], $total_dreavenings].min
end
CharSettings['current_lottery_attendance'][pc.noun] = CharSettings['current_lottery_attendance'][pc.noun].to_i + 1
}

And the first two lines are only needed if you want another script or hook to be able to access those settings.
[/quote]

The reason I have it setup in such a wonky way is because I do these events in groups, sometimes it's just 1 group, sometimes it's as much as 3, but each person should only get credit for attending once. The script checks each person at the table before beginning and adds 1, but sometimes people come to the table on their own outside of their chosen group to help send mana and if they arrive early enough they would be counted twice.

The easiest way I could figure to fix this problem at the time was to create a global variable that another script sets to nil when the entire event is over, so when the event is first started the global variable is equaled to the CharSetting attendance, then when someone is counted it adds 1 from the global variable since that number is going to remain static no matter how many times they are counted.

There is probably an easier way though, I tend to make things difficult :p

Not sure why I'm using the temp_attendance_value part though, I think at some point I was using this value for something else as well.

Tgo01
10-02-2016, 06:13 PM
The easiest way I could figure to fix this problem at the time was to create a global variable that another script sets to nil when the entire event is over, so when the event is first started the global variable is equaled to the CharSetting attendance, then when someone is counted it adds 1 from the global variable since that number is going to remain static no matter how many times they are counted.

Actually first I tried adding everyone already counted to an Array then I wouldn't +1 their value again if they were already in the Array, but that didn't fix the counting everything twice problem so I went with this to see if that would fix the problem, which it didn't. Now that the +2 counting problem is fixed, and this solution isn't fixing counting people who come to the table twice, I'll try going back to the Array thing.