is there a way to apply dry and solid principal - ruby-on-rails
I am working on this code to make it shorter so that it could be easier to study or read and I have but advanced to apply the dry and solid principle so could you help me with how to refactor this ruby on rails code which contains some if statements to do this.so that it becomes more easy to read and shorter using those principles.
if brand.rating = high
if price_reference < 15
price_suggestion = (price_reference - product_database.shipping_cost * 0.75) * 1.1
price_original = price_suggestion
elsif price_reference < 25
price_suggestion = (price_reference - product_database.shipping_cost * 0.775) * 1.1
price_original = price_suggestion
elsif price_reference < 50
price_suggestion = (price_reference - product_database.shipping_cost * 0.8) * 1.1
price_original = price_suggestion
elsif price_reference < 75
price_suggestion = (price_reference - product_database.shipping_cost * 0.825) * 1.1
price_original = price_suggestion
elsif price_reference < 100
price_suggestion = (price_reference - product_database.shipping_cost * 0.85) * 1.1
price_original = price_suggestion
elsif price_reference < 200
price_suggestion = (price_reference - product_database.shipping_cost * 0.875) * 1.1
price_original = price_suggestion
elsif price_reference < 400
price_suggestion = (price_reference - product_database.shipping_cost * 0.9) * 1.1
price_original = price_suggestion
elsif price_reference < 600
price_suggestion = (price_reference - product_database.shipping_cost * 0.925) * 1.1
price_original = price_suggestion
else
price_suggestion = (price_reference - product_database.shipping_cost * 0.95) * 1.1
price_original = price_suggestion
elsif brand.rating = low
if price_reference < 15
price_suggestion = (price_reference - product_database.shipping_cost * 0.75) * 0.9
price_original = price_suggestion
elsif price_reference < 25
price_suggestion = (price_reference - product_database.shipping_cost * 0.775) * 0.9
price_original = price_suggestion
elsif price_reference < 50
price_suggestion = (price_reference - product_database.shipping_cost * 0.8) * 0.9
price_original = price_suggestion
elsif price_reference < 75
price_suggestion = (price_reference - product_database.shipping_cost * 0.825) * 0.9
price_original = price_suggestion
elsif price_reference < 100
price_suggestion = (price_reference - product_database.shipping_cost * 0.85) * 0.9
price_original = price_suggestion
elsif price_reference < 200
price_suggestion = (price_reference - product_database.shipping_cost * 0.875) * 0.9
price_original = price_suggestion
elsif price_reference < 400
price_suggestion = (price_reference - product_database.shipping_cost * 0.9) * 0.9
price_original = price_suggestion
elsif price_reference < 600
price_suggestion = (price_reference - product_database.shipping_cost * 0.925) * 0.9
price_original = price_suggestion
else
price_suggestion = (price_reference - product_database.shipping_cost * 0.95) * 0.9
price_original = price_suggestion
else
if price_reference < 15
price_suggestion = (price_reference - product_database.shipping_cost * 0.75) * 1
price_original = price_suggestion
elsif price_reference < 25
price_suggestion = (price_reference - product_database.shipping_cost * 0.775) * 1
price_original = price_suggestion
elsif price_reference < 50
price_suggestion = (price_reference - product_database.shipping_cost * 0.8) * 1
price_original = price_suggestion
elsif price_reference < 75
price_suggestion = (price_reference - product_database.shipping_cost * 0.825) * 1
price_original = price_suggestion
elsif price_reference < 100
price_suggestion = (price_reference - product_database.shipping_cost * 0.85) * 1
price_original = price_suggestion
elsif price_reference < 200
price_suggestion = (price_reference - product_database.shipping_cost * 0.875) * 1
price_original = price_suggestion
elsif price_reference < 400
price_suggestion = (price_reference - product_database.shipping_cost * 0.9) * 1
price_original = price_suggestion
elsif price_reference < 600
price_suggestion = (price_reference - product_database.shipping_cost * 0.925) * 1
price_original = price_suggestion
else
price_suggestion = (price_reference - product_database.shipping_cost * 0.95) * 1
price_original = price_suggestion
end
Maybe something like:
def suggest_price(price_reference, shipping_cost)
[
[15, 0.75],
[25, 0.775],
[50, 0.8],
... etc ...
].each do |price_point, shipping_modifier|
if price_reference < price_point
return price_reference - shipping_cost * shipping_modifier
end
end
return price_reference - shipping_cost * 0.95
end
def price_modifier(brand)
if brand.rating == high
1.1
elsif brand.rating == low
0.9
else
1
end
end
price_original = price_modifier(brand) * suggest_price(price_reference, product_database.shipping_cost)
I'm not suggesting that's perfect code but it's a way you could approach it. You'd probably want the price points and modifiers in a constant.
You could apply some OOP. In the Brand class you could use some .case statements to make it more readable...
def prices
case self.rating
when 'high"
case
when price_reference < 15
(price_reference - product_database.shipping_cost * 0.75) * 1.1
when price_reference < 25
(price_reference - product_database.shipping_cost * 0.775) * 1.1
when price_reference < 50
(price_reference - product_database.shipping_cost * 0.8) * 1.1
etc...
when 'low'
case
etc...
else
etc...
end
end
A nested case statement is a bit easier to read. Also you are doing a lot of unneeded variable reassignment. Remember that Ruby always returns the last statement it evaluates. So when you call the method on a member of the Brand class you can use it like this:
brand = Brand.new(rating: 'high', price_reference: '25')
#let's assume product_database.shipping_cost = 5
brand.prices
#returns the value 23.2375 which came from (25 - 5 * 0.775) * 1.1
There are many ways to do this. You could abstract out a lot more of your code by creating some hash dictionaries to contain the values of each formula and then do variable substitution to call them. Try to thing in terms of objects and methods. Everything in Ruby is an object of some sort and you can create methods to call on those objects that call other methods and use other objects.
Related
Hi, I am creating a simpleplatformer game with love2d, I got a problem in the collisions
In my player script. I called a function to check is if a tile is collided with the player. The basic tile collisions has been made, but I got some problems. When the player jump while colliding with the wall, the player stop. When the player is falling while colliding with the wall, the player stop. I think the problem is in the Y collision checking part, but I can't figure out how to solve it. --------------------- Collision Check ---------------------- local box = Vt2:new(self.pos.x + self.vel.x * dt * self.dirXTemp, self.pos.y + self.vel.y * dt) for i = 1, #collTile do local tile = collTile[i] local isColl = BdBoxCollision(box, self.size, tile.pos, tile.size) if isColl[1] == true and isColl[2] == true and isColl[3] == true and isColl[4] == true then local isOnWall = false if self.pos.y + self.size.y > tile.pos.y then -- X Collision if box.x + self.size.x / 2 < tile.pos.x + tile.size.x / 2 then if box.x + self.size.x > tile.pos.x then if self.dirX == 1 then self.vel.x = 0 isOnWall = true end end end if box.x + self.size.x / 2 > tile.pos.x + tile.size.x / 2 then if box.x < tile.pos.x + tile.size.x then if self.dirX == -1 then self.vel.x = 0 isOnWall = true end end end end if box.y + self.size.y / 2 < tile.pos.y + tile.size.y / 2 then -- Y Collision if box.y + self.size.y > tile.pos.y and self.pos.y + self.size.y < tile.pos.y + 8 then if isOnWall == false then self.pos.y = tile.pos.y - self.size.y self.vel.y = 0 end end elseif box.y + self.size.y / 2 > tile.pos.y + tile.size.y / 2 then if box.y < tile.pos.y + tile.size.y then self.vel.y = self.gravity end end end end ::skip:: self.pos.x = self.pos.x + self.vel.x * dt self.pos.y = self.pos.y + self.vel.y * dt
Calling all parent and child nodes - SceneKit
I have a 3D car object with some pan and tap gestures on it and everything is working fine. The problem is that I found myself need specific angels for the camera to look at each part when I'm zooming it in as its a car and has so many parts, So I wrote all parent and child nodes to specify each of them. But I feel that it's not a good practice. Is there another way to do that? let parentNodeName = result.node.parent?.name if parentNodeName == "up-side"{ scnCameraOrbit.eulerAngles.x = 2.3 + Float.pi scnCameraOrbit.eulerAngles.y = Float.pi * 1.0 } else if parentNodeName == "front-side"{ if nodeName == "window-front"{ scnCameraOrbit.eulerAngles.x = 2.8 + Float.pi scnCameraOrbit.eulerAngles.y = Float.pi + 3.16 } else if nodeName == "hood"{ scnCameraOrbit.eulerAngles.x = 2.95 + Float.pi scnCameraOrbit.eulerAngles.y = Float.pi + 3.16 } else if nodeName == "bumper-front"{ scnCameraOrbit.eulerAngles.x = 3.45 + Float.pi scnCameraOrbit.eulerAngles.y = Float.pi + 3.16 } else{ scnCameraOrbit.eulerAngles.x = 3.45 + Float.pi scnCameraOrbit.eulerAngles.y = Float.pi + 3.16 } } else if parentNodeName == "back-side"{ if nodeName == "window-rear"{ scnCameraOrbit.eulerAngles.x = 2.9 + Float.pi scnCameraOrbit.eulerAngles.y = Float.pi * 1.0 } else if nodeName == "bumper-rear"{ scnCameraOrbit.eulerAngles.x = 3.4 + Float.pi scnCameraOrbit.eulerAngles.y = Float.pi * 1.0 } else if nodeName == "trunk"{ scnCameraOrbit.eulerAngles.x = 3.0 + Float.pi scnCameraOrbit.eulerAngles.y = Float.pi * 1.0 } else{ scnCameraOrbit.eulerAngles.x = 3.4 + Float.pi scnCameraOrbit.eulerAngles.y = Float.pi * 1.0 } } else if parentNodeName == "left-side"{ scnCameraOrbit.eulerAngles.x = -Float.pi * 0.0 scnCameraOrbit.eulerAngles.y = -3 * Float.pi * 1.2 } else if parentNodeName == "right-side"{ scnCameraOrbit.eulerAngles.x = -Float.pi * 0.0 scnCameraOrbit.eulerAngles.y = -2 * Float.pi * 1.2 } else{ return }
The IF tests are only called one time on hit test (click), right? If so... To avoid some of the nested IF's complexity, you might try some enumeration techniques < 24701075 >, quite a few examples in this post - read carefully, some of this is dated and new Swift features are available. You'll need 2 sets (I believe), one for the parent node names and then one set for the node names. Not sure about efficiency, but clarity would improve... opinions vary, but code readability and avoiding debug problems is usually a higher priority for me unless performance is a real problem.
rails assign attributes to instance
I am trying to calculate how much the total cost of my transaction will be. And to test I am running Transaction.last.calculate_total_payment, it is returning a BigDecimal which is what I want but none of the attributes are being updated on the instance after. What am I doing wrong? class Transaction < ActiveRecord::Base has_one :auction has_one :bid belongs_to :inventory_part TIER0 = 0 TIER1 = 5_000 TIER2 = 50_000 TIER3 = 500_000 TIER4 = 1_000_000 . . . . def calculate_total_payment part = self.bid.part_price self.tax = part * self.tax_rate if self.bid.tx.shipping_account self.final_shipping_cost = 0 else # testing purposes self.final_shipping_cost = self.bid.est_shipping_cost end price_before_fees = part + self.tax + self.final_shipping_cost if price_before_fees < TIER1 #5,000 self.bid_aero_fee = price_before_fees * 0.025 self.armor_fee = price_before_fees * 0.015 elsif price_before_fees < TIER2 #50,000 self.bid_aero_fee = (price_before_fees - TIER1) * 0.015 + 125 self.armor_fee = (price_before_fees - TIER1) * 0.01 + 75 elsif price_before_fees < TIER3 #500,000 self.bid_aero_fee = (price_before_fees - TIER2) * 0.0125 + 800 self.armor_fee = (price_before_fees - TIER2) * 0.0075 + 525 elsif price_before_fees < TIER4 #1,000,000 self.bid_aero_fee = (price_before_fees - TIER3) * 0.0075 + 6425 self.armor_fee = (price_before_fees - TIER3) * 0.005 + 3900 else # anything over a million self.bid_aero_fee = (price_before_fees - TIER4) * 0.0075 + 10175 self.armor_fee = (price_before_fees - TIER4) * 0.0035 + 6400 end self.total_fee = self.armor_fee + self.bid_aero_fee self.total_amount = price_before_fees + self.total_fee end end
You are never calling save in the calculate_total_payment method. You need to explicitly save the object for it to be persisted in the DB.
You should call save! at the end if you want to make your changes persistent in the database. Without this, it will modify the object in place (so changes will disappear after reloading of fetching the object again).
How to analyze Julia memory allocation and code coverage results
I am writing a package for Bayesian inference using Gibbs sampling. Since these methods are generally computationally expensive, I am very concerned about the performance of my code. In fact, speed was the reason I moved from Python to Julia. After implementing Dirichlet Process Model I analyzed the code using Coverage.jl and the --track-allocation=user commandline option. Here is the coverage results - #= - DPM - - Dirichlet Process Mixture Models - - 25/08/2015 - Adham Beyki, odinay#gmail.com - - =# - - type DPM{T} - bayesian_component::T - K::Int64 - aa::Float64 - a1::Float64 - a2::Float64 - K_hist::Vector{Int64} - K_zz_dict::Dict{Int64, Vector{Int64}} - - DPM{T}(c::T, K::Int64, aa::Float64, a1::Float64, a2::Float64) = new(c, K, aa, a1, a2, - Int64[], (Int64 => Vector{Int64})[]) - end 1 DPM{T}(c::T, K::Int64, aa::Real, a1::Real, a2::Real) = DPM{typeof(c)}(c, K, convert(Float64, aa), - convert(Float64, a1), convert(Float64, a2)) - - function Base.show(io::IO, dpm::DPM) - println(io, "Dirichlet Mixture Model with $(dpm.K) $(typeof(dpm.bayesian_component)) components") - end - - function initialize_gibbs_sampler!(dpm::DPM, zz::Vector{Int64}) - # populates the cluster labels randomly 1 zz[:] = rand(1:dpm.K, length(zz)) - end - - function DPM_sample_hyperparam(aa::Float64, a1::Float64, a2::Float64, K::Int64, NN::Int64, iters::Int64) - - # resampling concentration parameter based on Escobar and West 1995 352 for n = 1:iters 3504 eta = rand(Distributions.Beta(aa+1, NN)) 3504 rr = (a1+K-1) / (NN*(a2-log(NN))) 3504 pi_eta = rr / (1+rr) - 3504 if rand() < pi_eta 0 aa = rand(Distributions.Gamma(a1+K, 1/(a2-log(eta)))) - else 3504 aa = rand(Distributions.Gamma(a1+K-1, 1/(a2-log(eta)))) - end - end 352 aa - end - - function DPM_sample_pp{T1, T2}( - bayesian_components::Vector{T1}, - xx::T2, - nn::Vector{Float64}, - pp::Vector{Float64}, - aa::Float64) - 1760000 K = length(nn) 1760000 #inbounds for kk = 1:K 11384379 pp[kk] = log(nn[kk]) + logpredictive(bayesian_components[kk], xx) - end 1760000 pp[K+1] = log(aa) + logpredictive(bayesian_components[K+1], xx) 1760000 normalize_pp!(pp, K+1) 1760000 return sample(pp[1:K+1]) - end - - - function collapsed_gibbs_sampler!{T1, T2}( - dpm::DPM{T1}, - xx::Vector{T2}, - zz::Vector{Int64}, - n_burnins::Int64, n_lags::Int64, n_samples::Int64, n_internals::Int64; max_clusters::Int64=100) - - 2 NN = length(xx) # number of data points 2 nn = zeros(Float64, dpm.K) # count array 2 n_iterations = n_burnins + (n_samples)*(n_lags+1) 2 bayesian_components = [deepcopy(dpm.bayesian_component) for k = 1:dpm.K+1] 2 dpm.K_hist = zeros(Int64, n_iterations) 2 pp = zeros(Float64, max_clusters) - 2 tic() 2 for ii = 1:NN 10000 kk = zz[ii] 10000 additem(bayesian_components[kk], xx[ii]) 10000 nn[kk] += 1 - end 2 dpm.K_hist[1] = dpm.K 2 elapsed_time = toq() - 2 for iteration = 1:n_iterations - 352 println("iteration: $iteration, KK: $(dpm.K), KK mode: $(indmax(hist(dpm.K_hist, - 0.5:maximum(dpm.K_hist)+0.5)[2])), elapsed time: $elapsed_time") - 352 tic() 352 #inbounds for ii = 1:NN 1760000 kk = zz[ii] 1760000 nn[kk] -= 1 1760000 delitem(bayesian_components[kk], xx[ii]) - - # remove the cluster if empty 1760000 if nn[kk] == 0 166 println("\tcomponent $kk has become inactive") 166 splice!(nn, kk) 166 splice!(bayesian_components, kk) 166 dpm.K -= 1 - - # shifting the labels one cluster back 830166 idx = find(x -> x>kk, zz) 166 zz[idx] -= 1 - end - 1760000 kk = DPM_sample_pp(bayesian_components, xx[ii], nn, pp, dpm.aa) - 1760000 if kk == dpm.K+1 171 println("\tcomponent $kk activated.") 171 push!(bayesian_components, deepcopy(dpm.bayesian_component)) 171 push!(nn, 0) 171 dpm.K += 1 - end - 1760000 zz[ii] = kk 1760000 nn[kk] += 1 1760000 additem(bayesian_components[kk], xx[ii]) - end - 352 dpm.aa = DPM_sample_hyperparam(dpm.aa, dpm.a1, dpm.a2, dpm.K, NN, n_internals) 352 dpm.K_hist[iteration] = dpm.K 352 dpm.K_zz_dict[dpm.K] = deepcopy(zz) 352 elapsed_time = toq() - end - end - - function truncated_gibbs_sampler{T1, T2}(dpm::DPM{T1}, xx::Vector{T2}, zz::Vector{Int64}, - n_burnins::Int64, n_lags::Int64, n_samples::Int64, n_internals::Int64, K_truncation::Int64) - - NN = length(xx) # number of data points - nn = zeros(Int64, K_truncation) # count array - bayesian_components = [deepcopy(dpm.bayesian_component) for k = 1:K_truncation] - n_iterations = n_burnins + (n_samples)*(n_lags+1) - dpm.K_hist = zeros(Int64, n_iterations) - states = (ASCIIString => Int64)[] - n_states = 0 - - tic() - for ii = 1:NN - kk = zz[ii] - additem(bayesian_components[kk], xx[ii]) - nn[kk] += 1 - end - dpm.K_hist[1] = dpm.K - - # constructing the sticks - beta_VV = rand(Distributions.Beta(1.0, dpm.aa), K_truncation) - beta_VV[end] = 1.0 - π = ones(Float64, K_truncation) - π[2:end] = 1 - beta_VV[1:K_truncation-1] - π = log(beta_VV) + log(cumprod(π)) - - elapsed_time = toq() - - for iteration = 1:n_iterations - - println("iteration: $iteration, # active components: $(length(findn(nn)[1])), mode: $(indmax(hist(dpm.K_hist, - 0.5:maximum(dpm.K_hist)+0.5)[2])), elapsed time: $elapsed_time \n", nn) - - tic() - for ii = 1:NN - kk = zz[ii] - nn[kk] -= 1 - delitem(bayesian_components[kk], xx[ii]) - - # resampling label - pp = zeros(Float64, K_truncation) - for kk = 1:K_truncation - pp[kk] = π[kk] + logpredictive(bayesian_components[kk], xx[ii]) - end - pp = exp(pp - maximum(pp)) - pp /= sum(pp) - - # sample from pp - kk = sampleindex(pp) - zz[ii] = kk - nn[kk] += 1 - additem(bayesian_components[kk], xx[ii]) - - for kk = 1:K_truncation-1 - gamma1 = 1 + nn[kk] - gamma2 = dpm.aa + sum(nn[kk+1:end]) - beta_VV[kk] = rand(Distributions.Beta(gamma1, gamma2)) - end - beta_VV[end] = 1.0 - π = ones(Float64, K_truncation) - π[2:end] = 1 - beta_VV[1:K_truncation-1] - π = log(beta_VV) + log(cumprod(π)) - - # resampling concentration parameter based on Escobar and West 1995 - for internal_iters = 1:n_internals - eta = rand(Distributions.Beta(dpm.aa+1, NN)) - rr = (dpm.a1+dpm.K-1) / (NN*(dpm.a2-log(NN))) - pi_eta = rr / (1+rr) - - if rand() < pi_eta - dpm.aa = rand(Distributions.Gamma(dpm.a1+dpm.K, 1/(dpm.a2-log(eta)))) - else - dpm.aa = rand(Distributions.Gamma(dpm.a1+dpm.K-1, 1/(dpm.a2-log(eta)))) - end - end - end - - nn_string = nn2string(nn) - if !haskey(states, nn_string) - n_states += 1 - states[nn_string] = n_states - end - dpm.K_hist[iteration] = states[nn_string] - dpm.K_zz_dict[states[nn_string]] = deepcopy(zz) - elapsed_time = toq() - end - return states - end - - - function posterior{T1, T2}(dpm::DPM{T1}, xx::Vector{T2}, K::Int64, K_truncation::Int64=0) 2 n_components = 0 1 if K_truncation == 0 1 n_components = K - else 0 n_components = K_truncation - end - 1 bayesian_components = [deepcopy(dpm.bayesian_component) for kk=1:n_components] 1 zz = dpm.K_zz_dict[K] - 1 NN = length(xx) 1 nn = zeros(Int64, n_components) - 1 for ii = 1:NN 5000 kk = zz[ii] 5000 additem(bayesian_components[kk], xx[ii]) 5000 nn[kk] += 1 - end - 1 return([posterior(bayesian_components[kk]) for kk=1:n_components], nn) - end - And here is the memory allocation: - #= - DPM - - Dirichlet Process Mixture Models - - 25/08/2015 - Adham Beyki, odinay#gmail.com - - =# - - type DPM{T} - bayesian_component::T - K::Int64 - aa::Float64 - a1::Float64 - a2::Float64 - K_hist::Vector{Int64} - K_zz_dict::Dict{Int64, Vector{Int64}} - - DPM{T}(c::T, K::Int64, aa::Float64, a1::Float64, a2::Float64) = new(c, K, aa, a1, a2, - Int64[], (Int64 => Vector{Int64})[]) - end 0 DPM{T}(c::T, K::Int64, aa::Real, a1::Real, a2::Real) = DPM{typeof(c)}(c, K, convert(Float64, aa), - convert(Float64, a1), convert(Float64, a2)) - - function Base.show(io::IO, dpm::DPM) - println(io, "Dirichlet Mixture Model with $(dpm.K) $(typeof(dpm.bayesian_component)) components") - end - - function initialize_gibbs_sampler!(dpm::DPM, zz::Vector{Int64}) - # populates the cluster labels randomly 0 zz[:] = rand(1:dpm.K, length(zz)) - end - - function DPM_sample_hyperparam(aa::Float64, a1::Float64, a2::Float64, K::Int64, NN::Int64, iters::Int64) - - # resampling concentration parameter based on Escobar and West 1995 0 for n = 1:iters 0 eta = rand(Distributions.Beta(aa+1, NN)) 0 rr = (a1+K-1) / (NN*(a2-log(NN))) 0 pi_eta = rr / (1+rr) - 0 if rand() < pi_eta 0 aa = rand(Distributions.Gamma(a1+K, 1/(a2-log(eta)))) - else 0 aa = rand(Distributions.Gamma(a1+K-1, 1/(a2-log(eta)))) - end - end 0 aa - end - - function DPM_sample_pp{T1, T2}( - bayesian_components::Vector{T1}, - xx::T2, - nn::Vector{Float64}, - pp::Vector{Float64}, - aa::Float64) - 0 K = length(nn) 0 #inbounds for kk = 1:K 0 pp[kk] = log(nn[kk]) + logpredictive(bayesian_components[kk], xx) - end 0 pp[K+1] = log(aa) + logpredictive(bayesian_components[K+1], xx) 0 normalize_pp!(pp, K+1) 0 return sample(pp[1:K+1]) - end - - - function collapsed_gibbs_sampler!{T1, T2}( - dpm::DPM{T1}, - xx::Vector{T2}, - zz::Vector{Int64}, - n_burnins::Int64, n_lags::Int64, n_samples::Int64, n_internals::Int64; max_clusters::Int64=100) - - 191688 NN = length(xx) # number of data points 96 nn = zeros(Float64, dpm.K) # count array 0 n_iterations = n_burnins + (n_samples)*(n_lags+1) 384 bayesian_components = [deepcopy(dpm.bayesian_component) for k = 1:dpm.K+1] 2864 dpm.K_hist = zeros(Int64, n_iterations) 176 pp = zeros(Float64, max_clusters) - 48 tic() 0 for ii = 1:NN 0 kk = zz[ii] 0 additem(bayesian_components[kk], xx[ii]) 0 nn[kk] += 1 - end 0 dpm.K_hist[1] = dpm.K 0 elapsed_time = toq() - 0 for iteration = 1:n_iterations - 5329296 println("iteration: $iteration, KK: $(dpm.K), KK mode: $(indmax(hist(dpm.K_hist, - 0.5:maximum(dpm.K_hist)+0.5)[2])), elapsed time: $elapsed_time") - 16800 tic() 28000000 #inbounds for ii = 1:NN 0 kk = zz[ii] 0 nn[kk] -= 1 0 delitem(bayesian_components[kk], xx[ii]) - - # remove the cluster if empty 0 if nn[kk] == 0 161880 println("\tcomponent $kk has become inactive") 0 splice!(nn, kk) 0 splice!(bayesian_components, kk) 0 dpm.K -= 1 - - # shifting the labels one cluster back 69032 idx = find(x -> x>kk, zz) 42944 zz[idx] -= 1 - end - 0 kk = DPM_sample_pp(bayesian_components, xx[ii], nn, pp, dpm.aa) - 0 if kk == dpm.K+1 158976 println("\tcomponent $kk activated.") 14144 push!(bayesian_components, deepcopy(dpm.bayesian_component)) 4872 push!(nn, 0) 0 dpm.K += 1 - end - 0 zz[ii] = kk 0 nn[kk] += 1 0 additem(bayesian_components[kk], xx[ii]) - end - 0 dpm.aa = DPM_sample_hyperparam(dpm.aa, dpm.a1, dpm.a2, dpm.K, NN, n_internals) 0 dpm.K_hist[iteration] = dpm.K 14140000 dpm.K_zz_dict[dpm.K] = deepcopy(zz) 0 elapsed_time = toq() - end - end - - function truncated_gibbs_sampler{T1, T2}(dpm::DPM{T1}, xx::Vector{T2}, zz::Vector{Int64}, - n_burnins::Int64, n_lags::Int64, n_samples::Int64, n_internals::Int64, K_truncation::Int64) - - NN = length(xx) # number of data points - nn = zeros(Int64, K_truncation) # count array - bayesian_components = [deepcopy(dpm.bayesian_component) for k = 1:K_truncation] - n_iterations = n_burnins + (n_samples)*(n_lags+1) - dpm.K_hist = zeros(Int64, n_iterations) - states = (ASCIIString => Int64)[] - n_states = 0 - - tic() - for ii = 1:NN - kk = zz[ii] - additem(bayesian_components[kk], xx[ii]) - nn[kk] += 1 - end - dpm.K_hist[1] = dpm.K - - # constructing the sticks - beta_VV = rand(Distributions.Beta(1.0, dpm.aa), K_truncation) - beta_VV[end] = 1.0 - π = ones(Float64, K_truncation) - π[2:end] = 1 - beta_VV[1:K_truncation-1] - π = log(beta_VV) + log(cumprod(π)) - - elapsed_time = toq() - - for iteration = 1:n_iterations - - println("iteration: $iteration, # active components: $(length(findn(nn)[1])), mode: $(indmax(hist(dpm.K_hist, - 0.5:maximum(dpm.K_hist)+0.5)[2])), elapsed time: $elapsed_time \n", nn) - - tic() - for ii = 1:NN - kk = zz[ii] - nn[kk] -= 1 - delitem(bayesian_components[kk], xx[ii]) - - # resampling label - pp = zeros(Float64, K_truncation) - for kk = 1:K_truncation - pp[kk] = π[kk] + logpredictive(bayesian_components[kk], xx[ii]) - end - pp = exp(pp - maximum(pp)) - pp /= sum(pp) - - # sample from pp - kk = sampleindex(pp) - zz[ii] = kk - nn[kk] += 1 - additem(bayesian_components[kk], xx[ii]) - - for kk = 1:K_truncation-1 - gamma1 = 1 + nn[kk] - gamma2 = dpm.aa + sum(nn[kk+1:end]) - beta_VV[kk] = rand(Distributions.Beta(gamma1, gamma2)) - end - beta_VV[end] = 1.0 - π = ones(Float64, K_truncation) - π[2:end] = 1 - beta_VV[1:K_truncation-1] - π = log(beta_VV) + log(cumprod(π)) - - # resampling concentration parameter based on Escobar and West 1995 - for internal_iters = 1:n_internals - eta = rand(Distributions.Beta(dpm.aa+1, NN)) - rr = (dpm.a1+dpm.K-1) / (NN*(dpm.a2-log(NN))) - pi_eta = rr / (1+rr) - - if rand() < pi_eta - dpm.aa = rand(Distributions.Gamma(dpm.a1+dpm.K, 1/(dpm.a2-log(eta)))) - else - dpm.aa = rand(Distributions.Gamma(dpm.a1+dpm.K-1, 1/(dpm.a2-log(eta)))) - end - end - end - - nn_string = nn2string(nn) - if !haskey(states, nn_string) - n_states += 1 - states[nn_string] = n_states - end - dpm.K_hist[iteration] = states[nn_string] - dpm.K_zz_dict[states[nn_string]] = deepcopy(zz) - elapsed_time = toq() - end - return states - end - - - function posterior{T1, T2}(dpm::DPM{T1}, xx::Vector{T2}, K::Int64, K_truncation::Int64=0) 0 n_components = 0 0 if K_truncation == 0 0 n_components = K - else 0 n_components = K_truncation - end - 0 bayesian_components = [deepcopy(dpm.bayesian_component) for kk=1:n_components] 0 zz = dpm.K_zz_dict[K] - 0 NN = length(xx) 0 nn = zeros(Int64, n_components) - 0 for ii = 1:NN 0 kk = zz[ii] 0 additem(bayesian_components[kk], xx[ii]) 0 nn[kk] += 1 - end - 0 return([posterior(bayesian_components[kk]) for kk=1:n_components], nn) - end - What I don't seem to understand is why for instance a simple assignment which only runs twice, allocates 191688 units (I assume the unit is Bytes, I am not sure though). .cov: 2 NN = length(xx) # number of data points .mem: 191688 NN = length(xx) # number of data points or this one is worse: cov: 352 #inbounds for ii = 1:NN mem: 28000000 #inbounds for ii = 1:NN
The answer is briefly mentioned in the docs, "Under the user setting, the first line of any function directly called from the REPL will exhibit allocation due to events that happen in the REPL code itself." Also possibly relevant: "More significantly, JIT-compilation also adds to allocation counts, because much of Julia’s compiler is written in Julia (and compilation usually requires memory allocation). The recommended procedure is to force compilation by executing all the commands you want to analyze, then call Profile.clear_malloc_data() to reset all allocation counters." The bottom line: that first line is being blamed for allocations that happen elsewhere, because it's the first line to start reporting allocation again.
Dragging object onto container and flagging as occupied
I have multiple objects and multiple containers, My plan is that any object can be dropped on any container, but once a container has an object dropped on it, I want it to be occupied and not allow any more objects on to it. Is there an isOcuppied call or something like that, I cant find any examples of this. local function onTouch( event ) local t = event.target local phase = event.phase if "began" == phase then -- Make target the top-most object local parent = t.parent parent:insert( t ) display.getCurrentStage():setFocus( t ) -- Spurious events can be sent to the target, e.g. the user presses -- elsewhere on the screen and then moves the finger over the target. -- To prevent this, we add this flag. Only when it's true will "move" -- events be sent to the target. t.isFocus = true -- Store initial position t.x0 = event.x - t.x t.y0 = event.y - t.y elseif t.isFocus then if "moved" == phase then -- Make object move (we subtract t.x0,t.y0 so that moves are -- relative to initial grab point, rather than object "snapping"). t.xScale = 1.7 t.yScale = 1.7 t.x = event.x - t.x0 t.y = event.y - t.y0 --t1 = t1..t.value elseif "ended" == phase or "cancelled" == phase then for i = 1, #posX do if (((t.x >= ((sizeX/2) + posX[i] - ((2/3) * sizeX))) and (t.y >= ((sizeY/2) + posY - ((1/3) * sizeY))) and (t.x <= ((sizeX/2) + posX[i] + ((2/3) * sizeX))) and (t.y <= ((sizeY/2) + posY + ((1/3) * sizeY)))) or ((t.x >= ((sizeX/2) + posX[i] - ((1/3) * sizeX))) and (t.y >= ((sizeY/2) + posY - ((2/3) * sizeY))) and (t.x <= ((sizeX/2) + posX[i] + ((1/3) * sizeX))) and (t.y <= ((sizeY/2) + posY + ((2/3) * sizeY)))) or ((t.x >= ((sizeX/2) + posX[i] - ((1/2) * sizeX))) and (t.y >= ((sizeY/2) + posY - ((1/2) * sizeY))) and (t.x <= ((sizeX/2) + posX[i] + ((1/2) * sizeX))) and (t.y <= ((sizeY/2) + posY + ((1/2) * sizeY))))) then t.x, t.y = posX[i] + (sizeX/2), posY + (sizeY/2); elseif (((t.x >= ((sizeX/2) + posX1[i] - ((2/3) * sizeX))) and (t.y >= ((sizeY/2) + posY1 - ((1/3) * sizeY))) and (t.x <= ((sizeX/2) + posX1[i] + ((2/3) * sizeX))) and (t.y <= ((sizeY/2) + posY1 + ((1/3) * sizeY)))) or ((t.x >= ((sizeX/2) + posX1[i] - ((1/3) * sizeX))) and (t.y >= ((sizeY/2) + posY1 - ((2/3) * sizeY))) and (t.x <= ((sizeX/2) + posX1[i] + ((1/3) * sizeX))) and (t.y <= ((sizeY/2) + posY1 + ((2/3) * sizeY)))) or ((t.x >= ((sizeX/2) + posX1[i] - ((1/2) * sizeX))) and (t.y >= ((sizeY/2) + posY1 - ((1/2) * sizeY))) and (t.x <= ((sizeX/2) + posX1[i] + ((1/2) * sizeX))) and (t.y <= ((sizeY/2) + posY1 + ((1/2) * sizeY))))) then t.x, t.y = posX1[i] + (sizeX/2), posY1 + (sizeY/2); t2[i] = t.value --t1 = t1..t.value -- elseif (((t.x >= ((sizeX/2) + posX2 - ((2/3) * sizeX))) and (t.y >= ((sizeY/2) + posY2 - ((1/3) * sizeY))) and (t.x <= ((sizeX/2) + posX2 + ((2/3) * sizeX))) and (t.y <= ((sizeY/2) + posY2 + ((1/3) * sizeY)))) or ((t.x >= ((sizeX/2) + posX2 - ((1/3) * sizeX))) and (t.y >= ((sizeY/2) + posY2 - ((2/3) * sizeY))) and (t.x <= ((sizeX/2) + posX2 + ((1/3) * sizeX))) and (t.y <= ((sizeY/2) + posY2 + ((2/3) * sizeY)))) or ((t.x >= ((sizeX/2) + posX2 - ((1/2) * sizeX))) and (t.y >= ((sizeY/2) + posY2 - ((1/2) * sizeY))) and (t.x <= ((sizeX/2) + posX2 + ((1/2) * sizeX))) and (t.y <= ((sizeY/2) + posY2 + ((1/2) * sizeY))))) then -- t.x, t.y = posX2 + (sizeX/2), posY2 + (sizeY/2); end end t1 = t1..t.value t.xScale = 1 t.yScale = 1 --print(tile.label) display.getCurrentStage():setFocus( nil ) t.isFocus = false --n = n + 1 --value = " " end end Here is my code as it stands, Also Im I have a value attached to each tile e.g tile a = "A", currently I'm just appending a string each time a tile is moved, but I want the string or maybe use a table to only be appended when the tile has been put in a container. For example if one letter is in the wrong place and I move it to the right place I have touched it twice so my final string will be wrong
Why not set a value on your container: myContainer.isOccupied = false Then in your event handler, when every you get to your ended phase you can simply do a check: if not myContainer.isOccupied then -- code to drop myContainer.isOccupied = true end