DevToys-app / DevToys

A Swiss Army knife for developers.
https://devtoys.app/
MIT License
27.23k stars 1.46k forks source link

Number Base Converter - Custom base #384

Closed Andret2344 closed 2 years ago

Andret2344 commented 2 years ago

What's the Problem?

No response

Solution/Idea

Now number base formatter allows only converting between binary, octal, decimal and hexadecimal number bases. But It is possible to use different bases, e.g. 7, 3 or 12. How about allowing to decide about input and output number base for conversion by typing number between 1 (unary system) and (let's say) 36 (all uppercase alphanumerics).

Alternatives

Using this website

Priorities

Capability Priority
Allow to choose input and output number base Must
Properly handle negative numbers Should
Have no upper limits of numbers Could
Allow to add "another" row with different (or same...) number base output Could

DevToys Version

Version 1.0.3.0 | X64 | RELEASE | 7c7c02a | 7c7c02a

Comments

No response

youkai95 commented 2 years ago

I have something like this already done, @veler I would like to take this issue. Here are some interesting details like having a custom character dictionary to map the input to a custom base.

If you agree to implement this, I could have a fully working PR in a couple of days.

Andret2344 commented 2 years ago

Glad to hear you want to implement this, @youkai95! Can you please, for clarity, share the UI you are going to implement, to be able to debate over it?

youkai95 commented 2 years ago

@Andret2344 honestly I think it is time to remake this UI. Now with a custom base it would see too awkward with 4 fixed bases to convert to and a new input accepting/showing the value converted from a custom base.

With this feature an input for the base number will be needed, and we could accept another input for the conversion dictionary, if we want to. This could break the limit of the maximum base size. Anyways it is true that this UI could lack of UX if I just add a couple of fields... I am not sure about how to make this comfortable for the user, in addition to the fact that I am not very skilled with xaml UI designs. If you want to lend me a hand with this, I will gladly accept it!

(I could upload an image later with a mock if you wish, here are 3:30am)

Andret2344 commented 2 years ago

Yes, just an image with placeholders would be great.

I'm not skilled in C# at all, so I cannot offer any support, unfortunately.

youkai95 commented 2 years ago

Yes, just an image with placeholders would be great.

I'm not skilled in C# at all, so I cannot offer any support, unfortunately.

@Andret2344 Ok, no problem. Now I am going to sleep... In a while I will upload a mock of what I have already done.

expikr commented 2 years ago

Maybe some inspiration here

youkai95 commented 2 years ago

Sorry for the delay, I had some affairs to attend to. @Andret2344 this could be a mockup of how we could get things done. I tried to include all the possible features on it.

This design could have a few problems, in example: the format option could lead to problems if we use custom base dictionaries as there could exist differences between characters case for the conversion. I could work on a dictionary input validation to accept formatting conversions, perhaps I dont feel like having this feature included...

Maybe we should discuss a bit more this feature before pushing a solution to the repo. Please, @veler I would like to have some considerations from you. I have already done the code to convert from/to a custom base using a custom dictionary, this is more a UX discussion.

This is a mockup for these new changes. base_converter_mockup

Andret2344 commented 2 years ago

The UI is generally great, IMO. If it comes to the dictionary, In fact, the dictionary field could accept only uppercase letters, I mean changing the input case to upper case. Then a and A both will be A. Additionally, every char in the field must be unique.

The format option seems useless now, as there is no way of formatting a number of a base 7. On the other hand, converting to common base would be nice to have the output formatted.

@veler We would be really happy to hear your opinion and suggestions, because there are a few doubts

veler commented 2 years ago

Hello,

Thank you for this suggestion and sorry for the late reply here. I'd like @btiteux opinion here too.

Regarding my own opinion, I have to admit that in my day-to-day work I NEVER need to convert numbers, so I'm probably not well positioned to tell what's useful and what's not except by listening to user feedback, which is what I'm trying to do here.

Originally, @btiteux and I designed the current tool with the mindset of keeping the amount of clicks the lowest possible. This made us choose to take the current approach where you choose what the input is, and then all the supported output would be computed at one. Then the user would have to take what fits best its need. No need for an extra click to choose what the input should be converted to.

Now, let's see your proposed approach and allow me to brainstorm it while writing πŸ™‚

Overall, I like the UI. Like @Andret2344 said, it generally looks great. If I understand correctly by looking at the mock, Base dictionary, Input base number and Output base number are text box and number value box. I can imagine some challenge for the user: let's say the user is a newbie at number base conversion like me, how do I know exactly what I should put in these boxes?

This makes me think that Input base number and Output base number should probably be Combo Box with a predefined list of possibilities such like 16 (hexadecimal), 12 (duodecimal), 10 (decimal)...etc. That would prevent issues where user put a wrong value in Input base number and Output base number, but it would also limit the user to a certain list of possible number base, although I believe Octal, Decimal, Binary and Hexadecimal are the most common number base for a reason, so I'm wondering if it actually makes sense to allow the user to do pretty much any sort of number base.

Now, for the custom base dictionary, it sounds to me like a very advanced option that user should be able to completely ignore and not question what is that? when seeing the UI. Perhaps it should be placed in an expandable control, like the ones we have in RegEx Tester. Finally, let's take one of the most common developer profiles in the software industry: full stack web developer ==> I'm wondering how often web developers need such an amount of customization when doing a number base conversion. Does anyone have any idea?

The reason why I'm challenging this approach a little bit is that I'd like to keep things simple. The more possibilities the tool offers, the busier the UI needs to be. The busier the UI is, the less attractive it is and the more confusing it becomes to the user and the more challenging it becomes for us to make it fit in the Overlay Mode.

image

What do you folks think about it? I'm not opposed to do this change, but before saying let's do this I want to make sure to understand the goal, how it works and who actually needs this.

expikr commented 2 years ago

Why not leave the current UI as-is and just Add an "Other Number Bases" collapsible section for things like different big/little endian types (and maybe signed unsigned etc) and among them could also be a more involved "custom" base one?

quoting @jwfxpr from #256:

In the collapsible section it would be great to have the RFC 4648 Base16, Base32, and Base64 encodings. Since these don't use 0..9 for the bottom ten digits, they need separate fields to typical 0..Z schemes.

Ref https://datatracker.ietf.org/doc/html/rfc4648

jwfxpr commented 2 years ago

Why not leave the current UI as-is and just Add an "Other Number Bases" collapsible section for things like different big/little endian types (and maybe signed unsigned etc) and among them could also be a more involved "custom" base one?

Yes, I agree with this. The current base converter UI works pretty well and covers the vast majority of use cases for the tool.

I also share @veler's curiosity about how important aritrary bases and dictionaries are to our target users. I get that arbitrary bases are possible and arbitrary dictionaries are cool, but could you offer us a use case for, e.g., using a base 7 number system which would just be stored in 8 bits of memory anyway? Or storing numbers in arbitrary base encoding dictionaries? πŸ€” Is there some obvious and important reason to use arbitrary bases and dictionaries that I'm missing here?

I suspect truly arbitrary number bases maybe belong in a hypothetical MathToys project, and our UI should be focused on the developer domain. Adding useful base dictionaries like those RFC4648 implementations, which are designed to minimise letter ambiguities like 0 O, etc, is far more useful to 99% of developers.

jwfxpr commented 2 years ago

Also, small point, there's no need for a field to enter the base for a custom dictionary. The length of the dictionary determines the base. 😊 0123456 -> base 7, etc.

Andret2344 commented 2 years ago

Hi all, thanks for taking part in the discussion.

Reading all your comments, I must admit the UI is really simple and simple enough for most users and use cases and adding them custom base to choose would only confuse newbies etc. So how about creating a switch labeled as "advanced mode" that would replace the current simple UI with the advanced on suggested by @youkai95?

Now, answering the @veler's doubts, the custom base wouldn't be widely used as it's not generally needed, and we should keep the current simple UI. The reason why custom base is needed is quite simple: learning and teaching. At the university, we were obliged to convert number in base 23 to number in base 7, or from base 19 to base 9. The only way to verify it was to convert calculations to base 10. On the other hand, as I'm teaching the conversions, it'd be very handy to simple convert it.

youkai95 commented 2 years ago

As @veler said, me neither had the need of converting a number to a base out of the common ones. I am not sure how much this change could be used, however as it is not something hard to do and there are people requesting it I decided to give it a try and look for a clean solution.

Maybe completely change the UI could be challenging for some dev that are not adapted to work with that level of customization. Also, expose the digits dictionary it is more like an entertainment than a feature because many people could confuse or make a wrong use of it (in addition, I do not think that someone could go out of [0-9a-f]).

If you prefer I could make a PR only with functionalities and leave the UI design to other person. As @xeonmc said, we could use a collapsible section and leave this level of customization out of the common features, or even we could give this a different point of view and use a new section...

@jwfxpr what if I decide to use a personal numeric alphabet? Among all the weird things, this is a very weird one, but ok... I could leave an open door for it XD Also, that accepts the possibility to change between different base64, base32 dictionaries as stated in RFC4648.

expikr commented 2 years ago

image

image

jwfxpr commented 2 years ago

That seems like the best compromise to me, @xeonmc. Minimal clutter, and the flexibility's there for those who need it. I think a drop-down is a good way to fold them together, and leaves us room if for some reason we have reason to implement other number base standards in futureπŸ‘

@Andret2344, @youkai95, thanks for engaging with us on this, it will be good to have the extra features implemented into the tool. 😊

For the "Custom base", I don't know of any standardized base alphabets beyond 64, so I think we should allow bases 2–64 and just use a basic 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/ alphabet.

Andret2344 commented 2 years ago

Just one question. How about allowing to add an extra line with another IO field? Something like this (with removing them as well... somehow)

image

youkai95 commented 2 years ago

How about allowing to add an extra line with another IO field?

Are you talking about allowing as many "Other" IOs as the user decides?

Andret2344 commented 2 years ago

How about allowing to add an extra line with another IO field?

Are you talking about allowing as many "Other" IOs as the user decides?

yes, indeed

expikr commented 2 years ago

some refinement: image

expikr commented 2 years ago

I propose also adding a "Roman Numerals" base as demonstration of multi-character digit symbols

btiteux commented 2 years ago

Hello,

I would prefer to keep the current UI for the "base" case and add a advanced mode switch.

This way we could switch between base (current UI) and advance (new UI) and you can add all the fields you need without reducing the margin between them.

The Advanced mode should be a new ViewModel and a new View.

What do you think?

Andret2344 commented 2 years ago

Hello,

I would prefer to keep the current UI for the "base" case and add a advanced mode switch.

This way we could switch between base (current UI) and advance (new UI) and you can add all the fields you need without reducing the margin between them.

The Advanced mode should be a new ViewModel and a new View.

What do you think?

I suggested it a few comments above

Hi all, thanks for taking part in the discussion.

Reading all your comments, I must admit the UI is really simple and simple enough for most users and use cases and adding them custom base to choose would only confuse newbies etc. So how about creating a switch labeled as "advanced mode" that would replace the current simple UI with the advanced on suggested by @youkai95?

And I agree it would also work, but the solution suggested by @xeonmc would also work. Now we only need to decide which solution is to be implemented. @veler, I guess your vote is deciding now

btiteux commented 2 years ago

Yes I know @Andret2344 just can quote on the mobile app don't know why 😁.

We need to check the render in compact mode too πŸ™‚

veler commented 2 years ago

Hello,

Like @btiteux and @Andret2344 suggested, I'd also prefer a toggle switch that would enable an Advance mode where the UI could, if we want, completely different.

UI

The default UI could like exactly like the current one, but with an extra option on the top:

image

Once "Advanced mode" is enabled, it could switch to a different UI like the following:

image

While I now do see the value for converting in more base than the 4 most we allowed by default, I'm still not convinced by the custom dictionary approach though. Except for study purposes, does anyone here ever need a custom dictionary of characters after doing a number base conversion?

PS: @youkai95 , what did you use to make your mock above? It looks nice. I used PowerPoint because I didn't feel like it worth using Figma, but your mockup look much fancier. 🀣

Implementation

Because it would have a different UI with a different mechanism, I'd suggest splitting the UI into 3 different views.

The last 2 User Control could be placed into a Border/Grid/ContentPresenter in the 1st one, and the Advanced Mode option would simply show one while hiding the other.

Each User Control should have its own View Model. The advanced and non-advanced User Control's View Model should be able to listen to the Format Number option so they react when the user interact with it. You can use Events or Messenger for this. Please put the common conversion logic into NumberBaseHelper and refactor whatever's needed to make both modes working smoothly without too much duplicated code. :)

Here is an example of how we send messages between View Models:

https://github.com/veler/DevToys/blob/07d84344352d2036fa1bd290607a4da444305c09/src/dev/impl/DevToys/ViewModels/Tools/GroupToolViewModelBase.cs#L25-L26

https://github.com/veler/DevToys/blob/07d84344352d2036fa1bd290607a4da444305c09/src/dev/impl/DevToys/ViewModels/Tools/GroupToolViewModelBase.cs#L36

https://github.com/veler/DevToys/blob/4cfcbbaf5004d61eca530791c6ce79653ffda86c/src/dev/impl/DevToys/ViewModels/MainPageViewModel.cs#L41

https://github.com/veler/DevToys/blob/4cfcbbaf5004d61eca530791c6ce79653ffda86c/src/dev/impl/DevToys/ViewModels/MainPageViewModel.cs#L371

What do you folks think about?

expikr commented 2 years ago

I feel like having a dropdown defaulting to Base-64 makes sense as a reasonable "fifth conversion". The user ignoring the dropdown and just doing his thing will just see it as yet another esoteric conversion. The user clicking on the dropdown out of curiosity will see all those options and, if he is confused, at least the burden of confusion has a cognitive cause-and-effect of "ok this dropdown is some weird stuff but I can just ignore it".

Andret2344 commented 2 years ago

Implementation

Because it would have a different UI with a different mechanism, I'd suggest splitting the UI into 3 different views.

  • 1 User Control that would only have the Advanced mode and Format number options.
  • 1 User Control for the non-advanced view, which would have the Hexadecimal, Decimal, Octal and Binary text boxes.
  • 1 User Control for the advanced view, which would have the Input base number option, Input, Output...etc.

The last 2 User Control could be placed into a Border/Grid/ContentPresenter in the 1st one, and the Advanced Mode option would simply show one while hiding the other.

Each User Control should have its own View Model. The advanced and non-advanced User Control's View Model should be able to listen to the Format Number option so they react when the user interact with it. You can use Events or Messenger for this. Please put the common conversion logic into NumberBaseHelper and refactor whatever's needed to make both modes working smoothly without too much duplicated code. :)

@veler I'm not sure Format number should be a common part. Above we agreed that is quite hard to format number out of the set of standard bases, so I guess it should be a part of the non-advanced view.

veler commented 2 years ago

@veler I'm not sure Format number should be a common part. Above we agreed that is quite hard to format number out of the set of standard bases, so I guess it should be a part of the non-advanced view.

Oh, you're correct! My bad!

expikr commented 2 years ago

Made a slightly different mockup:

image

jwfxpr commented 2 years ago

I have to say I prefer the simplicity of a single fifth field at the bottom, as in @xeonmc's mockups. It's simple, self-explanatory, and more flexible. I don't see an obvious place for the RFC4648 specs in the advanced mode option, for example. Adding other things later becomes a fresh debate over which view to alter in which way, versus just adding another option to the drop-down. 😊

Also, yeah, what are we all using for these mockups? I'm curious too πŸ˜†

expikr commented 2 years ago

Only MSPaint and nothing else. Make liberal use of transparency selection and Ctrl-stamping.

youkai95 commented 2 years ago

@veler a friend of mine shown me an app to make mockups and I just fallen in love with it. Its name is Balsamiq Mockups 3. I dont know if there is a new version but this one has everything needed for a good mockup. This app it is not free though...

Edit: I just noticed that it seems this app is free now and has been replaced by a new version... So I think you could use the same app for free πŸ˜ƒ

If all of you agree I will just make a PR with the logic needed to convert from/to a custom base using a custom dict, then we could just use that logic in the way we think it will be the correct way. My point is to review the code while we decide how to use it. Later we could finish the PR with the UI we decide.

veler commented 2 years ago

Hi all,

@youkai95 , thanks for the tip!

@xeonmc , @jwfxpr , @youkai95 , @btiteux , I think you folks convinced me. I think I actually prefer's xeonmc approach here now. Sorry for the change of mind so quickly.

That said, I'm concern by how this field would look like when DevToys is in Compact Overlay mode image

image

image

I feel like the UI of this specific field will be too small (+ imagine if "Other" and "Custom Dictionary" are taking 2-3 times this space in some other languages).

While I'm pointing out this concern, I don't necessarily have a good answer to it right now. Have you folks thought about it already, and/or imagined a different layout that would work with a small UI like this?

expikr commented 2 years ago

The way it could be implemented is that there is always a persistent dictionary as a separate row atop the input, just that it is hidden unless the Custom Dictionary option is selected. Then all that happens when the user selects one of the preset dropdowns is changing the content of that persistent (but invisible) dictionary field. Likewise with the custom base input field, it is also persistent but only visible when the right dropdown is selected.

So the implementation logic would be something like

  1. user selects a preset dropdown
  2. the preset dropdown populates the persistent field with its associated dictionary
  3. the base number is calculated from the populated dictionary field and updated
  4. the visibility state of the two elements is updated based on the selected dropdown-option's associated config
jwfxpr commented 2 years ago

(+ imagine if "Other" and "Custom Dictionary" are taking 2-3 times this space in some other languages).

I agree, I think the labels and fields need enough space for regionalisation. But to be honest, I think that this particular feature of the number base tool will be infrequently used (or frequently used by a small minority of users) and so, having to scroll down the compact overlay window to access the field(s) isn't such a problem.

Also, alongside that, I imagine that pretty much all the time that someone uses of the Number Base Converter tool, the user will be interested in one specific conversion: say, decimal to hex, octal to binary, etc. So that means there's an opportunity to make the interface more compact when in compact overlay mode (or whenever the tool's display area is below a threshold). Perhaps fold-out controls can appear for all the fields, such that only the two fields that the user cares about are visible.

I'll try to mock up what I mean... good excuse to try out Balsamiq!

So, normal view with no extra input fields for "Other":

Snapshot

Normal view with large extra input field for "Other":

Snapshot

When first entering compact overlay mode (or when the window shrinks below a set threshold), showing overflow for clarity:

Snapshot

With fields I don't need right now collapsed for compact usability:

Snapshot

I followed the general logic suggested by @xeonmc, which seems reasonable to me.

What do you think, @veler?

N.B., the specific placing of the chevron, especially around the configuration field set, is something I wasn't sure of, I have limited UX design experience. Left-hand-side margin seemed intuitively logical to me, but πŸ€·β€β™‚οΈ there's probably guidelines or best practice or whatever. This was just a general concept 😊

niyari commented 2 years ago

Personally, I find the standard Windows calculator ( calc.exe ) to have the best UI.

calculator It has a simple UI, but also allows pasting and copying of values. image

btiteux commented 2 years ago

The compact mode will be complicated. I made these wireframe to test with an Advanced Mode

Normal View image image

Compact View image

We need to keep the UI consistent with the others tools.

So if we made some changes on component for this tool we need to see the impact on the other tools too.

Andret2344 commented 2 years ago

Personally, I really like the @btiteux's UI mockup and in fact I was thinking about something exactly like this. The consistency is a really important argument. This approach also keeps the UI not overcomplicated with huge amount of fields to set it up

expikr commented 2 years ago

Per the suggestion of @niyari :

image

image

image

niyari commented 2 years ago

I wrote this code when I was interested in Base32, but there are several derivative versions of Base32. https://github.com/niyari/base32-ts/blob/0cba699ea43986bc6cbab9558de8d08ffee413c8/src/base32.ts#L62

Type Dic Comment
RFC4648_HEX '0123456789ABCDEFGHIJKLMNOPQRSTUV'
RFC3548 or RFC4648 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'
Clockwork Base32 '0123456789ABCDEFGHJKMNPQRSTVWXYZ' 1 I i L l = 1
crockford '0123456789ABCDEFGHJKMNPQRSTVWXYZ' Perhaps the specifications only contain numerical values.

Some users prefer A for 0x0 and some prefer 0. Some users prefer a dictionary that eliminates confusing strings. The list of dictionaries is likely to be large.

veler commented 2 years ago

Hello, Sorry for the late answer. I also prefer the last @btiteux mock up. The consistency is good, it works well with the Compact Mode and the Advanced option allows most users to have a restricted; not confusing UI on first place.

@youkai95 , would you like to have fun implementing it? :)

youkai95 commented 2 years ago

@youkai95 , would you like to have fun implementing it? :)

@veler I could give it a try but I have few experience working with UWP (however seems to be very similar to WPF), so I am not sure about how to correctly face this UI. I will use your previous recommendation as a guide.

I am pushing a draft PR (#430) for you to review what I have done at the moment while I begin with UI.

veler commented 2 years ago

Hello,

Sorry for the late answer again. UWP UI is quite similar to WPF, indeed. To implement it, you can create 2 new UserControls, as I mentioned above. At the end of the day, there would be 3 UserControls in the Views\Tools\Converters\NumberBaseConverter folder.

  1. NumberBaseConverterToolPage.xaml => This one would contains the common UI to the 2 mode. In short, it would have the Advanced mode option.
  2. NumberBaseConverterSimpleView.xaml => this one would have the current UI that we have in DevToys.
  3. NumberBaseConverterAdvancedView.xaml => this one would have the new UI when Advanced Mode option is enabled.

The 2 new user controls can be placed in the UI of NumberBaseConverterToolPage. You can use some binding along with a BooleanToVisibility converter to show/hide NumberBaseConverterSimpleView or NumberBaseConverterAdvancedView based on the value of Advanced mode option. There are plenty of placed where we use BooleanToVisibility in the solution. :)

Let me know if this help. :)