-
Notifications
You must be signed in to change notification settings - Fork 701
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
Handle download count round up to 1E+3K for when 999,500 <= count <=999,999 #4255
Conversation
++exp; | ||
} | ||
|
||
string format = v < 999 ? "{0:G3}{1}" : "{0:G4}{1}"; // If number is 999561 then v = 999.56 so with G3 which result in 1000k ~ 1E+03K, but with G4 it result in 999.6K. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added logic for handling v >= 999, we handle with 1 more precision , but I didn't for v< 999 otherwise it's kind of breaking experience for many users seeing too much detailed information.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't showing a 4th digit of precision when all other cases only show 3 also a kind of "breaking" experience?
How about if (v > 999.0) { v = 999.0; }
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zivkan
Ok. Taken your suggestion. Please check now.
@@ -64,15 +64,17 @@ public static string NumberToString(long number, IFormatProvider culture) | |||
|
|||
while (v >= 1000) | |||
{ | |||
v /= 1000; | |||
v = Math.Round(v / 1000, 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/ConverterTests.cs
Show resolved
Hide resolved
test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/ConverterTests.cs
Outdated
Show resolved
Hide resolved
@@ -47,8 +47,8 @@ private static bool IsHttpUrl(Uri uri) | |||
return (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps); | |||
} | |||
|
|||
private static readonly string[] _scalingFactor = new string[] { | |||
String.Empty, | |||
private static readonly string[] ScalingFactor = new string[] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this stay as _scalingFactor
?
https://github.com/NuGet/NuGet.Client/blob/dev/docs/coding-guidelines.md#c-coding-style
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is IDE suggested fix, it looks rule is bit different for static readonly
variable.
NuGet.Client/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs
Line 42 in f4ae349
private static readonly INuGetProjectContext EmptyNuGetProjectContext = new EmptyNuGetProjectContext(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this whole algorithm is too complex and there's a bug here where billions will look like 1.23G
because G
is specified for billions instead of B
. Does this scaling factor need to know about byte size and item count? If so then it would need to differentiate them.
I think we should simplify this method and get rid of the loop which is confusing and made you add this silly looking if statement:
// If number is 999561 then v = 999.56 so with G3 which result in 1000k ~ 1E+03K.
if (v > 999)
{
v = 999;
}
What do you think about this instead?
public static string NumberToString(long number, IFormatProvider culture)
{
const double thousand = 1000D;
const double million = 1000000D;
const double billion = 1000000000D;
const double trillion = 1000000000000D;
if (number >= trillion)
{
return (number / trillion).ToString("0.##T", culture);
}
if (number >= billion)
{
return (number / billion).ToString("0.##B", culture);
}
if (number >= million)
{
return (number / million).ToString("0.##M", culture);
}
if (number >= thousand)
{
return (number / thousand).ToString("0.##K", culture);
}
return number.ToString("G0", culture);
}
Then you can get rid of the ScalingFactor
array as well and this method makes waaaaay more sense.
We might need to methods:
ByteCountToString()
: Returns the number as bytes so KB, MB, GB, TB (kilobytes, megabytes, gigabytes, terabytes)
CountToString()
: Returns a number as a count so K, M, B, T (thousand, million, billion, trillion)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because G is specified for billions instead of B.
G is the SI (standard international) prefix. If we want to use B in English, then we need to make it a string resource to allow the translators to localize this into the correct value for each language. So that part of it is by-design, I think. See also NuGet/Home#10864
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well yeah while we're here we might as well localize it! Fix two bugs with one stone
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feel free to ping me to discuss if you want, I really think we should fix this code as a whole
@@ -47,8 +47,8 @@ private static bool IsHttpUrl(Uri uri) | |||
return (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps); | |||
} | |||
|
|||
private static readonly string[] _scalingFactor = new string[] { | |||
String.Empty, | |||
private static readonly string[] ScalingFactor = new string[] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this whole algorithm is too complex and there's a bug here where billions will look like 1.23G
because G
is specified for billions instead of B
. Does this scaling factor need to know about byte size and item count? If so then it would need to differentiate them.
I think we should simplify this method and get rid of the loop which is confusing and made you add this silly looking if statement:
// If number is 999561 then v = 999.56 so with G3 which result in 1000k ~ 1E+03K.
if (v > 999)
{
v = 999;
}
What do you think about this instead?
public static string NumberToString(long number, IFormatProvider culture)
{
const double thousand = 1000D;
const double million = 1000000D;
const double billion = 1000000000D;
const double trillion = 1000000000000D;
if (number >= trillion)
{
return (number / trillion).ToString("0.##T", culture);
}
if (number >= billion)
{
return (number / billion).ToString("0.##B", culture);
}
if (number >= million)
{
return (number / million).ToString("0.##M", culture);
}
if (number >= thousand)
{
return (number / thousand).ToString("0.##K", culture);
}
return number.ToString("G0", culture);
}
Then you can get rid of the ScalingFactor
array as well and this method makes waaaaay more sense.
We might need to methods:
ByteCountToString()
: Returns the number as bytes so KB, MB, GB, TB (kilobytes, megabytes, gigabytes, terabytes)
CountToString()
: Returns a number as a count so K, M, B, T (thousand, million, billion, trillion)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved for insertion into dev branch.
@jeffkl We previously had discussion on replacing |
I don't think changing the precision would be a breaking change but we could keep it as-is with |
5eca391
to
81160a2
Compare
81160a2
to
a456837
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, thanks for localizing it too. Update the PR description to say it fixes NuGet/Home#10864 ?
{ | ||
return string.Format( | ||
culture, | ||
"{0:G3}{1}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be better to include the {0:G3}
in the localized string? Maybe some cultures prefer to have a space between the number and the suffix, while others don't. For example 123 M
vs 123M
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zivkan
I moved into localized string, please review again.
</data> | ||
<data name="Thousand" xml:space="preserve"> | ||
<value>K</value> | ||
<comment>1.000 in short format notation</comment> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
English uses ,
for thousands separators, so while all of these comments use .
which is probably more common across the world, given our code and comments are in English, it looks a bit odd, and this one (thousands) can be mistaken for the number one (precise to 3 decimal places).
9fcdc5d
to
8695bb6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments on strings. I just want to make sure loc team will not get confused with two different meanings in the same string resource
</data> | ||
<data name="Trillion" xml:space="preserve"> | ||
<value>{0:G3}T</value> | ||
<comment>Trillions in short format notation</comment> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please specify which trillions are you referring to:
<comment>Trillions in short format notation</comment> | |
<comment>American trillions in short format notation</comment> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dominoFire
Does EU and US trillions use different notations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks you. Now I understand what milliard
actually means, previously I always thought it's just another regional spelling for million.
[InlineData(1939, "1.94K", "en-US")] | ||
[InlineData(1939, "1,94K", "da-DK")] | ||
[InlineData(9456, "9.46K", "en-US")] | ||
[InlineData(9456, "9,46K", "da-DK")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aortiz-msft
I thought about it but I believe it's available after localization team make translation for each different cultures. @dominoFire Please correct me if I'm wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, since NuGet.Client's localization happens in a different repo, we can't have unit tests that work the same and still pass both locally (that doesn't run MicroBuild's localization task) and on CI (which does run MicroBuild's localization task).
I believe that if we migrated to the same localization system/format that the rest of the dotnet org uses, then local builds would include it.
Bug
Fixes: NuGet/Home#8800
Fixes: NuGet/Home#10864
Regression? Last working version:
Description
For number higher than 999.5 fractional number(it's less than 1000) it round up to 1000 but it ends up 1E+3K, 1E+3M, 1E+3G text. This problem can be solved in many different ways, but I selected current approach which introduce least breaking change on UI screen, my change affect 0.1% ~ 1/1000 cases, so 999/1000 cases users wouldn't notice it any difference.
Update
Added localization after PR review comment. Now english users see
1B
instead of1G
, but depending on localization other users see differently.Previous experience on PMUI:
![image](https://user-images.githubusercontent.com/8766776/133132845-6bc08019-c6f2-4347-90cc-afe1ad894ce0.png)
New experience on PMUI:
![image](https://user-images.githubusercontent.com/8766776/133132686-35e0c460-1c85-451b-a1e1-8cb36b978208.png)
Original number
-Previous experience
-New experience
PR Checklist
PR has a meaningful title
PR has a linked issue.
Described changes
Tests
Documentation