What is the average mobile rating on Google PageSpeed Insights? - lighthouse

We use Google PageSpeed Insights as a marketing tool to compare the download speed of websites we do with what our competitors do. But so many mobile sites are rated in the 30s and wondered if that's what the average mobile rating is. Does anyone know? Thx

Short Answer
The average mobile rating is 31.
Long Answer.
An article I found after writing the below that answers the question
This article from tunetheweb has actually done the hard work for us here and gathered the data from httparchive. (give the article a read it has a wealth of interesting information!)
The below table taken from that article covers your question (the answer is 31 for the performance metric 50th percentile)
Percentile Performance Accessibility Best Practices SEO PWA
10 8 56 64 69 14
25 16 69 64 80 25
50 31 80 71 86 29
75 55 88 79 92 36
90 80 95 86 99 54
95 93 97 93 100 54
99 99 100 93 100 64
I have left the below in as the information may be useful to somebody but the above answers the question much better. At least my guess of 35 wasn't a millions miles away from the actual answer. hehe.
My original Answer
You would imagine that a score of 50 would be the average right? Nope!
Lighthouse uses a log-normal curve to create a curve that dictates scores.
The two key control points on that curve are the 25th percentile for the median (a score of 50 means you are in the top 25% effectively) and the 8th percentile for a score of 90.
The numbers used to determine these points are derived from http archive data.
You can explore the curve used for Time To Interactive scoring here as an example.
Now I am sure someone who is a lot better at maths than me can use that data to calculate the average score for a site, but I would estimate it to be around 35 for a mobile site, which is pretty close to what you have observed.
One thing I can do is provide how the scoring works based on those control points so you can see the various cutoff points etc. for each metric.
The below is taken from the maths module at https://github.com/paulirish/lh-scorecalc/tree/190bed715a3589601f314b3c8a50fb0fb147c121
I have also included the median and falloff values currently used in this calculation in the scoring variable.
To play with it use either the VALUE_AT_QUANTILE function to get what value you need to achieve a certain percentage (so to see the value for the 90th percentile for Time To Interactive you would use VALUE_AT_QUANTILE(7300, 2900, 0.9); (take median (7300) and falloff (2900) from TTI in the scoring variable and then enter the desired percentile as a decimal (90 -> 0.9)).
Similar for QUANTILE_AT_VALUE function which does the reverse (shows the percentile that a particular value would fall at). E.g. if you wanted to see what percentile a First CPU Idle time of 3200 gets you would use QUANTILE_AT_VALUE(6500, 2900, 3200).
Anyway I have gone a bit off tangent, but hopefully the above and below will let someone cleverer than me the info needed to work it out (I have included the weightings for each item as well in the weights variable).
const scoring = {
FCP: {median: 4000, falloff: 2000, name: 'First Contentful Paint'},
FMP: {median: 4000, falloff: 2000, name: 'First Meaningful Paint'},
SI: {median: 5800, falloff: 2900, name: 'Speed Index'},
TTI: {median: 7300, falloff: 2900, name: 'Time to Interactive'},
FCI: {median: 6500, falloff: 2900, name: 'First CPU Idle'},
TBT: {median: 600, falloff: 200, name: 'Total Blocking Time'}, // mostly uncalibrated
LCP: {median: 4000, falloff: 2000, name: 'Largest Contentful Paint'},
CLS: {median: 0.25, falloff: 0.054, name: 'Cumulative Layout Shift', units: 'unitless'},
};
const weights = {
FCP: 0.15,
SI: 0.15,
LCP: 0.25,
TTI: 0.15,
TBT: 0.25,
CLS: 0.05
};
function internalErf_(x) {
// erf(-x) = -erf(x);
var sign = x < 0 ? -1 : 1;
x = Math.abs(x);
var a1 = 0.254829592;
var a2 = -0.284496736;
var a3 = 1.421413741;
var a4 = -1.453152027;
var a5 = 1.061405429;
var p = 0.3275911;
var t = 1 / (1 + p * x);
var y = t * (a1 + t * (a2 + t * (a3 + t * (a4 + t * a5))));
return sign * (1 - y * Math.exp(-x * x));
}
function internalErfInv_(x) {
// erfinv(-x) = -erfinv(x);
var sign = x < 0 ? -1 : 1;
var a = 0.147;
var log1x = Math.log(1 - x*x);
var p1 = 2 / (Math.PI * a) + log1x / 2;
var sqrtP1Log = Math.sqrt(p1 * p1 - (log1x / a));
return sign * Math.sqrt(sqrtP1Log - p1);
}
function VALUE_AT_QUANTILE(median, falloff, quantile) {
var location = Math.log(median);
var logRatio = Math.log(falloff / median);
var shape = Math.sqrt(1 - 3 * logRatio - Math.sqrt((logRatio - 3) * (logRatio - 3) - 8)) / 2;
return Math.exp(location + shape * Math.SQRT2 * internalErfInv_(1 - 2 * quantile));
}
function QUANTILE_AT_VALUE(median, falloff, value) {
var location = Math.log(median);
var logRatio = Math.log(falloff / median);
var shape = Math.sqrt(1 - 3 * logRatio - Math.sqrt((logRatio - 3) * (logRatio - 3) - 8)) / 2;
var standardizedX = (Math.log(value) - location) / (Math.SQRT2 * shape);
return (1 - internalErf_(standardizedX)) / 2;
}
console.log("Time To Interactive (TTI) 90th Percentile Time:", VALUE_AT_QUANTILE(7300, 2900, 0.9).toFixed(0));
console.log("First CPU Idle time of 3200 score / percentile:", (QUANTILE_AT_VALUE(6500, 2900, 3200).toFixed(3)) * 100);

Related

How to find and update levels accordingly based on points?

I am creating a rails application which is like a game. So it has points and levels. For example: to become level one the user has to get atleast 100 points and again for level two the user has to reach level 2 the user has to collect 200 points. The level difference changes after every 10 levels i.e., The difference between each level changes after 10 levels always. By that I mean the difference in points between level one and two is 100 and the difference in points in level 11 and 12 is 150 and so on. There is no upper bound for levels.
Now my question is let's say a user's total points is 3150 and just got updated to 3155. What's the optimal solution to find the current level and update it if needed?
I can get a solution using while loops and again looping inside it which will give a result in O(n^2). I need something better.
I think this code works but I'm not sure if this is the best way to go about it
def get_level(points)
diff = 100
sum = 0
level = -1
current_level = 0
while level.negative?
10.times do |i|
current_level += 1
sum += diff
if points > sum
next
elsif points <= sum
level = current_level
break
end
end
diff += 50
end
puts level
end
I wrote a get_points function (it should not be difficult). Then based on it get_level function in which it was necessary to solve the quadratic equation to find high value, and then calc low.
If you have any questions, let me know.
Check output here.
#!/usr/bin/env python3
import math
def get_points(level):
high = (level + 1) // 10
low = (level + 1) % 10
high_point = 250 * high * high + 750 * high # (3 + high) * high // 2 * 500
low_point = (100 + 50 * high) * low
return low_point + high_point
def get_level(points):
# quadratic equation
a = 250
b = 750
c = -points
d = b * b - 4 * a * c
x = (-b + math.sqrt(d)) / (2 * a)
high = int(x)
remainder = points - (250 * high * high + 750 * high)
low = remainder // (100 + 50 * high)
level = high * 10 + low
return level
def main():
for l in range(0, 40):
print(f'{l:3d} {get_points(l - 1):5d}..{get_points(l) - 1}')
for level, (l, r) in (
(1, (100, 199)),
(2, (200, 299)),
(9, (900, 999)),
(10, (1000, 1149)),
(11, (1150, 1299)),
(19, (2350, 2499)),
(20, (2500, 2699)),
):
for p in range(l, r + 1): # for in [l, r]
assert get_level(p) == level, f'{p} {l}'
if __name__ == '__main__':
main()
Why did you set the value of a=250 and b = 750? Can you explain that to me please?
Let's write out every 10 level and the difference between points:
lvl - pnt (+delta)
10 - 1000 (+1000 = +100 * 10)
20 - 2500 (+1500 = +150 * 10)
30 - 4500 (+2000 = +200 * 10)
40 - 7000 (+2500 = +250 * 10)
Divide by 500 (10 levels * 50 difference changes) and received an arithmetic progression starting at 2:
10 - 2 (+2)
20 - 5 (+3)
30 - 9 (+4)
40 - 14 (+5)
Use arithmetic progression get points formula for level = k * 10 equal to:
sum(x for x in 2..k+1) * 500 =
(2 + k + 1) * k / 2 * 500 =
(3 + k) * k * 250 =
250 * k * k + 750 * k
Now we have points and want to find the maximum high such that point >= 250 * high^2 + 750 * high, i. e. 250 * high^2 + 750 * high - points <= 0. Value a = 250 is positive and branches of the parabola are directed up. Now we find the solution of quadratic equation 250 * high^2 + 750 * high - points = 0 and discard the real part (is high = int(x) in python script).

Smart algorithm to create unique exponential sequence steps between two values

I'm looking for a algorithm that returns 5 steps between 2 given dynamic values, including both starting values, with exponential growth. The returned values should be nicely rounded and unique.
Example:
range 100 - 10000 should return something like this:
100, 500, 2500, 5000, 10000
This is what i came up with so far (credit goes mostly to the SO thread I once found but can't recover):
min = 100
max = 10000
a = Array.new
loops = 5
factor = 2.5
for i in 0..loops-1
x = (max - min) * ( (i.to_f / (loops.to_f - 1.0)) ** factor ) + min
case x
when min
a[i] = x.to_i
when max
a[i] = x.to_i
when (min + 1).to_f..500
a[i] = (x.to_f / 250).round(0) * 250
when 500..2000
a[i] = (x.to_f / 500).round(0) * 500
else
a[i] = (x.to_f / 2500).round(0) * 2500
end
end
The result is adjustable with the factor, I found 2.5 to be working best. This works quite well already in most cases. Before rounding I get these values:
[100.0, 409.37, 1850.08, 4922.67, 10000.0]
But it does not check for duplicates that can occur in the rounding process, which happens mostly if the range is smaller:
100 - 1000
Raw: [100.0, 128.12, 259.09, 538.42, 1000.0]
Rounded: [100, 250, 250, 500, 1000]
5000 - 10000
Raw: [5000.0, 5156.25,5883.88, 7435.69, 10000.0]
Rounded: [5000, 5000, 5000, 7500, 10000]
Now I'm a little torn between discarding the whole code and trying to come up with a smarter calculation method that already includes rounding or just checking for duplicates on a second run - but I didn't get a satisfying result from any of those two options.
Does someone have a clue on how to integrate a duplicate check in the rounding or make the rounding more dynamic?

What Linear Mapping Function

What linear mapping function is required to map a gray image from [30-200] to [0, 255]?
I have already done some work and this is what I have come up with, but I would like to know if it's the correct way to do it:
min : 30, want to map to 0
mid : 85, want to map to 128
max : 200, want to map to 255
if (i <= mid), M(i) = 127*(i - min)/(mid - min)
if (i > mid), M(i) = 128 + (255 - 128)*(i - mid - 1)/(max - mid - 1);
This appears to be correct to me because:
if i = 30, it should map to 0. Plugging the information in:
M(30) = 127*(30-30)/(85 - 30) = 0
If i = 85, it should map to 127:
M(85) = 127*(85 - 30) / (85 - 30) = 127
If i = 200, it should map to 200:
M(200) = 128 + (255 - 128)*(200 - 85 - 1)/(200 - 85 - 1) = 255
Thank you.
If you apply a linear mapping, the middle of the first interval will be automatically mapped to the middle of the second interval (you can see it as Thales principle). So you need to apply only one equation: y=a.x+b
To solve this equation you have two information: a.30+b=0, and
a.200+b=255.
Then you solve this and you obtain: a=1.5, and b=-45.
And be careful, the middle of [30, 200] is not 85 but 115 (=30+85).
Finally you can check, if you apply 1.5*x-45=y, you successfully obtain: 30->0, 200->255, and 115->127.5

Extracting sampled Time Points

I have a matlab Curve from which i would like to plot and find Concentration values at 17 different time samples
Following is the curve from which i would like to extract Concentration values at 17 different time points
following are the time points in minutes
t = 0,0.25,0.50,1,1.5,2,3,4,9,14,19,24,29,34,39,44,49. minutes samples
Following is the Function which i have written to plot the above graph
function c_t = output_function_constrainedK2(t, a1, a2, a3,b1,b2,b3,td, tmax,k1,k2,k3)
K_1 = (k1*k2)/(k2+k3);
K_2 = (k1*k3)/(k2+k3);
DV_free= k1/(k2+k3);
c_t = zeros(size(t));
ind = (t > td) & (t < tmax);
c_t(ind)= conv(((t(ind) - td) ./ (tmax - td) * (a1 + a2 + a3)),(K_1*exp(-(k2+k3)*t(ind)+K_2)),'same');
ind = (t >= tmax);
c_t(ind)= conv((a1 * exp(-b1 * (t(ind) - tmax))+ a2 * exp(-b2 * (t(ind) - tmax))) + a3 * exp(-b3 * (t(ind) - tmax)),(K_1*exp(-(k2+k3)*t(ind)+K_2)),'same');
plot(t,c_t);
axis([0 50 0 1400]);
xlabel('Time[mins]');
ylabel('concentration [Mbq]');
title('Model :Constrained K2');
end
If possible, Kindly please suggest me some idea how i could possibly alter the above function so that i can come up with concentration values at 17 different time points stated above
Following are the input values that i have used to come up with the curve
output_function_constrainedK2(0:0.1:50,2501,18500,65000,0.5,0.7,0.3,3,8,0.014,0.051,0.07)
This will give you concentration values at the time points you wanted. You will have to put this inside the output_function_constrainedK2 function so that you can access the variables t and c_t.
T=[0 0.25 0.50 1 1.5 2 3 4 9 14 19 24 29 34 39 44 49];
concentration=interp1(t,c_t,T)

How to properly triangulate GSM cell towers to get a location?

First of all, I am trying to do all this disaster in c# (.net 4) so if you come up with some code to help me that would be appreciated but really anything would help at this point.
I have a situation where I have a device that can only get GSM Cell information (incidentally via the AT+KCELL command) so I have a collection of values about cell towers (each has LAC, MCC, MNC, Cell ID, Signal Strength and the first Timing Advance). I think, therefore, I am in a good place to be able to come up with some sort of longitude and latitude coordinate (albeit inaccurate, but, well meh). This is where I am reaching out for help because now my little brain is confused...
I can see various services that provide cell code resolution (Google, Open Cell ID, etc) and they take LAC,MCC etc as arguments and return a coordinate. I figure that what they return would, therefore, be the coordinate of the given tower I pass in. So in my case I could send off all the LACs etc that I have and get back a collection of longitude and latitudes. Brilliant, but that is not where my device is. Now I think I need to do some kind of triangulation and this is where my lack of knowledge is hurting me.
So am I right so far? Assuming I am, how do I perform this calculation (is there something out there that will tell me what to do with all these numbers or, even better, some open source library I can reference and feed all this stuff into to get something sensible)?
I'm assuming that I would need to use the timing advance to work out some approximate distance from a cell tower (maybe using the signal strength somehow) but what do I have to do? As you can tell - I am way out of my depth here!
For example, this is something I might get back from the aforementioned AT command:
5,74,33,32f210,157e,8101,50,0,79,3,32f210,157e,80f7,37,64,5,32f210,157e,810b,37,55,32,32f210,157e,9d3,27,41,33,32f210,157e,edf8,15
breaking it up and parsing it I would get (I hope I parse this right - there is a chance there is a bug in my parsing routine of course but it looks reasonable):
Number of cells: 5
Cell 1
LAC: 5502
MNC: 1
MCC: 232
Cell ID: 33025
Signal: 80
ARFCN: 74
BSIC: 33
Timing advance: 0
Longitude: 14.2565389
Latitude: 48.2248439
Cell 2
LAC: 5502
MNC: 1
MCC: 232
Cell ID: 33015
Signal: 55
ARFCN: 79
BSIC: 3
Longitude: 14.2637736
Latitude: 48.2331576
Cell 3
LAC: 5502
MNC: 1
MCC: 232
Cell ID: 33035
Signal: 55
ARFCN: 64
BSIC: 5
Longitude: 14.2488966
Latitude: 48.232513
Cell 4
LAC: 5502
MNC: 1
MCC: 232
Cell ID: 2515
Signal: 39
ARFCN: 55
BSIC: 32
Longitude: 14.2488163
Latitude: 48.2277972
Cell 5
LAC: 5502
MNC: 1
MCC: 232
Cell ID: 60920
Signal: 21
ARFCN: 41
BSIC: 33
Longitude: 14.2647612
Latitude: 48.2299558
So with all that information how do I find, in the most accurate way, where I actually am?
I can help you with a bit of the theory.
Triangulation is basically finding the intersection point of 3 circles.
Each mobile tower is the center of a circle. The size of the circle is relative to the signal strength of that tower.
The place where the 3 circles overlap is where the user is.
You can do some very basic triangulation as follows:
3 Towers at
tx1,ty1
tx2,ty2
tx3,ty3
With signal strengths s1, s2, s3
We calculate the weight of each signal. Essentially a number from 0 to 1 for each tower where the sum of the weights adds up to 1.
Weighted signal w1, w2, w3 where:
w1 = s1/(s1+s2+s3)
w2 = s2/(s1+s2+s3)
w3 = s3/(s1+s2+s3)
User will be at
x: (w1 * tx1 + w2 * tx2+ w3 * tx3)
y: (w1 * ty1 + w2 * ty2+ w3 * ty3)
Here is a working example using the values from your question:
s1 = 80
s2 = 55
s3 = 55
s4 = 55
s5 = 21
w1 = 80 / ( 80 + 55 + 55 + 55 + 21 )
w2 = 55 / ( 80 + 55 + 55 + 55 + 21 )
w3 = 55 / ( 80 + 55 + 55 + 55 + 21 )
w4 = 55 / ( 80 + 55 + 55 + 55 + 21 )
w5 = 21 / ( 80 + 55 + 55 + 55 + 21 )
w1 = 0.3007519
w2 = 0.2067669
w3 = 0.2067669
w4 = 0.2067669
w5 = 0.0789474
1. Longitude: 14.2565389
1. Latitude: 48.2248439
2. Longitude: 14.2637736
2. Latitude: 48.2331576
3. Longitude: 14.2488966
3. Latitude: 48.232513
4. Longitude: 14.2488163
4. Latitude: 48.2277972
5. Longitude: 14.2647612
5. Latitude: 48.2299558
Location Longitude =
14.2565389 * 0.3007519 +
14.2637736 * 0.2067669 +
14.2488966 * 0.2067669 +
14.2488163 * 0.2067669 +
14.2647612 * 0.0789474
Location Latitude: =
48.2248439 * 0.3007519 +
48.2331576 * 0.2067669 +
48.232513 * 0.2067669 +
48.2277972 * 0.2067669 +
48.2299558 * 0.0789474
Result Longitude: 14.255507
Result Latitude: 48.2291628
This is not an answer really but its a starter and I might add more to it:
The cell ids are published it seems:
http://openbmap.org/
I found this link from this wiki page that has links to other cell id data sources: http://en.wikipedia.org/wiki/Cell_ID )
see the bottom of the page the is a link to the cell id data:
http://openbmap.org/latest/cellular/raw/input_raw.zip
also i found this youtube video where a guys is playing around with some apps that have cell tower locations it seems:
http://www.youtube.com/watch?v=CYvVN5dJD7A
possibly between the cell ids and signal strength you can make a guess..
but AFAIK for general triangulation you need to know the exact location of at least three towers and your exact distance from them (this could be a rough distance with signal strength but it may just be too in accurate).
it seems like wikipedia is saying its done in this way.. use a combination of which cell you are in, the closest tower and signal strengths to get your location:
http://en.wikipedia.org/wiki/Mobile_phone_tracking

Resources