Skip to content
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

Update All SI Units #87

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

Conversation

tkuschel
Copy link

@tkuschel tkuschel commented Apr 6, 2023

I have been annoyed for a very long time that you can't just use all the units with the SI prefixes. For the electronics lectures at the university of applied sciences I asked students to use the scientific notation for the time being. Then I moved on to using conversion formulas. Long story short:
I implemented a third choice at the "Unit Settings "+"Basic conversion rules" called "All SI units". With this setting, for any unit, the possibility to enter all SI prefixes is given.
Example: Unit "µA" given. As a result from a question you have to enter e.g. "22 µA".
Now, with this "All SI units" - setting, all these answers are correct:

  • 22 µA
  • 0.022 mA
  • 22e-6 A
  • 22000 pA
  • 22 uA

Additionally this functionality works with any unit e.g. kΩ, VA, kmol, mol, cd, ...

  • new feature: possiblity to enter µ (mu, and greek letter) in addition to u
  • new feature: conversion rules: add fullsiunit beside of commonsiunit and none.
  • removed: not used function get_unit_mapping(), and get_dimension_list()

@PhilippImhof
Copy link
Collaborator

Thank you very much for this nice contribution. I will have a closer look at it soon. You chose a good time, because I am currently rewriting the whole parsing/evaluation engine and was thinking about ways to improve the unit stuff.

@tkuschel
Copy link
Author

tkuschel commented Apr 6, 2023

If there are more then one Units given in the field "Unit" e.g.
"mΩ = mohm = mm^2 kg s^-3 A^-2"

This did not work any more. Also I think the "mm^2 kg s^-3 A^-2" did not work in the past, that could be also implemented to use prefixes for such a unit.
Several testcases at http://159.69.109.101/course/view.php?id=2``

It looks like that a refactoring of the whole prefix calculation would be fine. For instance the following feature would be great:

  • prefix handling with m^2 or m^3
  • very complex handling of this->mapping and additonal_rules; could be more flexible and easier data structures

I updated my solution, still room for improvements...

Thomas

@PhilippImhof
Copy link
Collaborator

Thanks! The whole unit thing suffers from a huge lack of unit and, to a lesser extent, acceptance testing. I think now is a good moment to add some tests. Don't worry, I will try to find some time to write them :)

I also agree with your remarks about prefix calculation. That code is very old and comes with some limitations, especially w.r.t. maintainability. My ultimate goal is to rewrite that part, but that can only be done once the new parsing/evaluation engine is ready.

Copy link
Collaborator

@PhilippImhof PhilippImhof left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again for your contribution.

I have finally found some time to look at the code and made a few remarks. I have not yet tested the functionality, because I would like to prepare some automated testing for the unit conversion (as it is now) first.

F: m u n p f;
T: k m u n p;
H: k m u n p;
Ω: u µ μ m k M G T P;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is (U+03A9 / GREEK CAPITAL LETTER OMEGA). I suggest adding Ω (U+2126 / OHM SIGN) as well.

CHANGES.md Outdated
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please include the changelog entries in the PR, so they can be included upon preparation of the next release, together with the correct version number and release date.

'E' => 1e18, 'Z' => 1e21, 'Y' => 1e24, 'f' => 1e-15, 'a' => 1e-18, 'z' => 1e-21, 'y' => 1e-24,
'R' => 1e27, 'Q' => 1e30, 'r' => 1e-27, 'q' => 1e-30 );
// For convenience, u can be used for micro-, rather than "mu", which has multiple similar UTF representations.
// Note: All UTF representations of µ can be used too.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Note: All UTF representations of µ can be used too.
// Note: One can use GREEK SMALL LETTER MU (U+03BC) or MICRO SIGN (U+00B5).

*/
public function parse_prefix_unit($unit) {
if (is_array($unit)) {
throw new Exception('parse_prefix_unit does not handle arrays!');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The string should be in lang/en/qtype_formulas.php and imported with get_string.

public function parse_prefix_unit($unit) {
if (is_array($unit)) {
throw new Exception('parse_prefix_unit does not handle arrays!');
return '';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return '';

Unreachable code.

foreach (static::$prefix_scale_factors as $i => $prefix) {
if (str_starts_with($unit,$i)) {
$unit = substr($unit, strlen($i));
break;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The break is not needed IMHO.

Suggested change
break;

if (preg_match('/['.self::$unit_exclude_symbols.']+/', $unit_name)) {
throw new Exception('"'.$unit_name.'" unit contains unaccepted character.');
if (preg_match('/['.self::$rule_exclude_symbols.']+/', $unit_name)) {
throw new Exception('"'.$unit_name.'" rule contains unaccepted character.');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The string should be in lang/en/qtype_formulas.php and imported with get_string. (I know it wasn't done like this before, but if we're at it...)

public function assign_default_rules($default_id, $default_rules) {
if ($this->default_id == $default_id) {
public function assign_default_rules($default_id, $default_rules, $part_unit = '') {
if (($default_id == 2) && ($part_unit != $this->part_unit)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would probably be better to have a class constant ALL_SI_UNITS = 2 and use it here. This would make the code easier to understand in a few years.

');

$this->basicunitconversionrule[2] = array(get_string('allsiunits', 'qtype_formulas'), '');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure I am getting this right: You changed the conversion rules for commonsiunit, but you define allsiunits anyway. But don't the changes bring the desired functionality to commonsiunit as well? Would there be any reason for a user to stick with commonsiunit versus allsiunits?

version.php Outdated
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not change the file version.php for the moment. It will be updated during the preparation of the release, in order to avoid merge conflicts among concurrent PRs.

@PhilippImhof
Copy link
Collaborator

I have added a very basic test for the "common SI unit" conversion rules and took the liberty to merge this into your PR. We will be able to extend that test for the stuff you added.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants