384 self addConversion:(4/3) from:#teaspoon to:#fldr. |
382 self addConversion:(4/3) from:#teaspoon to:#fldr. |
385 |
383 |
386 |
384 |
387 "/ ---------------- temperature ---------------- |
385 "/ ---------------- temperature ---------------- |
388 |
386 |
389 self addConversion:[:d | d * 1.8 + 32] from:#celsius to:#fahrenheit. |
387 self addConversion:[:d | d * 1.8 + 32] from:#celsius to:#fahrenheit. |
390 self addConversion:[:f | (f - 32) / 1.8] from:#fahrenheit to:#celsius. |
388 self addConversion:[:f | (f - 32) / 1.8] from:#fahrenheit to:#celsius. |
|
389 self addConversion:[:d | d + 273.15] from:#celsius to:#kelvin. |
|
390 self addConversion:[:k | k - 273.15] from:#kelvin to:#celsius. |
391 |
391 |
392 "/ ---------------- nature ---------------- |
392 "/ ---------------- nature ---------------- |
393 Constants at:#planckLength put:#(1.616e-35 #'m'). |
393 Constants at:#planckLength put:#(1.616e-35 #'m'). |
394 Constants at:#planckMass put:#(2.176-8 #'Kg'). |
394 Constants at:#planckMass put:#(2.176-8 #'Kg'). |
395 Constants at:#planckTime put:#(5.391e-44 #'s'). |
395 Constants at:#planckTime put:#(5.391e-44 #'s'). |
575 convert:howMany from:sourceUnit to:destUnit |
575 convert:howMany from:sourceUnit to:destUnit |
576 "given a value in sourceUnit (symbolic), try to convert it |
576 "given a value in sourceUnit (symbolic), try to convert it |
577 to destUnit (symbolic); return nil, if the conversion is |
577 to destUnit (symbolic); return nil, if the conversion is |
578 unknown." |
578 unknown." |
579 |
579 |
|
580 ^ self convert:howMany from:sourceUnit to:destUnit pairsAlreadyTried:(OrderedCollection new) |
|
581 |
|
582 "direct - how many meters are there in two inches: |
|
583 UnitConverter convert:2 from:#inch to:#meter |
|
584 |
|
585 reverse - how many inches are there in one meter |
|
586 UnitConverter convert:1 from:#meter to:#inch |
|
587 |
|
588 with alias: |
|
589 UnitConverter convert:1 from:#inch to:#m |
|
590 UnitConverter convert:1 from:#inch to:#mm |
|
591 UnitConverter convert:1 from:#inch to:#millimeter |
|
592 UnitConverter convert:1 from:#inch to:#nanometer |
|
593 UnitConverter convert:1 from:#mm to:#km |
|
594 UnitConverter convert:1 from:#km to:#foot |
|
595 |
|
596 indirect: |
|
597 UnitConverter convert:1 from:#mm to:#twip |
|
598 UnitConverter convert:1 from:#inch to:#twip |
|
599 UnitConverter convert:1 from:'letterH' to:#point |
|
600 UnitConverter convert:1 from:'letterlH' to:#point |
|
601 |
|
602 UnitConverter convert:5 from:#barrel to:#liter |
|
603 UnitConverter convert:10 from:#kilogram to:#carat |
|
604 |
|
605 UnitConverter convert:1 from:#liter to:#floz |
|
606 UnitConverter convert:1 from:#floz to:#liter |
|
607 UnitConverter convert:1 from:#oz to:#gram |
|
608 UnitConverter convert:1 from:#ounce to:#gram |
|
609 |
|
610 UnitConverter convert:37 from:#celsius to:#fahrenheit -> 98.6 |
|
611 UnitConverter convert:37 from:#celsius to:#kelvin -> 310.15 |
|
612 UnitConverter convert:0 from:#celsius to:#kelvin -> 273.15 |
|
613 UnitConverter convert:0 from:#kelvin to:#celsius -> -273.15 |
|
614 UnitConverter convert:0 from:#kelvin to:#fahrenheit -> -459.67 |
|
615 UnitConverter convert:0 from:#fahrenheit to:#celsius -> -17.7777777777778 |
|
616 UnitConverter convert:0 from:#fahrenheit to:#kelvin -> 255.372222222222 |
|
617 |
|
618 " |
|
619 |
|
620 "Created: / 31-05-1996 / 16:23:38 / cg" |
|
621 "Modified (comment): / 18-09-2017 / 09:02:09 / cg" |
|
622 ! |
|
623 |
|
624 convert:howMany from:sourceUnit to:destUnit pairsAlreadyTried:pairsAlready |
|
625 "given a value in sourceUnit (symbolic), try to convert it |
|
626 to destUnit (symbolic); return nil, if the conversion is |
|
627 unknown." |
|
628 |
580 |u conversions alias rslt sU dU const val unit |
629 |u conversions alias rslt sU dU const val unit |
581 i suNumerator suDenominator duNumerator duDenominator uN uD |
630 i suNumerator suDenominator duNumerator duDenominator uN uD |
582 sF1 sF2 dF1 dF2 |
631 sF1 sF2 dF1 dF2 |
583 s d| |
632 s d| |
584 |
633 |
590 |
639 |
591 "/ somehow, recursion must end ... |
640 "/ somehow, recursion must end ... |
592 sourceUnit == destUnit ifTrue:[ |
641 sourceUnit == destUnit ifTrue:[ |
593 ^ howMany |
642 ^ howMany |
594 ]. |
643 ]. |
595 |
644 thisContext isReallyRecursive ifTrue:[ |
|
645 ^ self noConversionFrom:sourceUnit to:destUnit. |
|
646 ]. |
|
647 (pairsAlready includes:(sourceUnit->destUnit)) ifTrue:[ |
|
648 ^ self noConversionFrom:sourceUnit to:destUnit. |
|
649 ]. |
|
650 pairsAlready add:(sourceUnit->destUnit). |
|
651 |
596 sourceUnit isSymbol ifFalse:[ |
652 sourceUnit isSymbol ifFalse:[ |
597 s := sourceUnit withoutSeparators. |
653 s := sourceUnit withoutSeparators. |
598 sU := s asSymbolIfInterned. |
654 sU := s asSymbolIfInterned. |
599 sU notNil ifTrue:[ |
655 sU notNil ifTrue:[ |
600 ^ self convert:howMany from:sU to:destUnit |
656 ^ self convert:howMany from:sU to:destUnit pairsAlreadyTried:pairsAlready |
601 ]. |
657 ]. |
602 (s startsWith:$() ifTrue:[ |
658 (s startsWith:$() ifTrue:[ |
603 (s endsWith:$)) ifTrue:[ |
659 (s endsWith:$)) ifTrue:[ |
604 s := s copyFrom:2 to:(s size - 1). |
660 s := s copyFrom:2 to:(s size - 1). |
605 ^ self convert:howMany from:s to:destUnit |
661 ^ self convert:howMany from:s to:destUnit pairsAlreadyTried:pairsAlready |
606 ] |
662 ] |
607 ]. |
663 ]. |
608 ]. |
664 ]. |
609 destUnit isSymbol ifFalse:[ |
665 destUnit isSymbol ifFalse:[ |
610 d := destUnit withoutSeparators. |
666 d := destUnit withoutSeparators. |
611 dU := d asSymbolIfInterned. |
667 dU := d asSymbolIfInterned. |
612 dU notNil ifTrue:[ |
668 dU notNil ifTrue:[ |
613 ^ self convert:howMany from:sourceUnit to:dU |
669 ^ self convert:howMany from:sourceUnit to:dU pairsAlreadyTried:pairsAlready |
614 ]. |
670 ]. |
615 (d startsWith:$() ifTrue:[ |
671 (d startsWith:$() ifTrue:[ |
616 (d endsWith:$)) ifTrue:[ |
672 (d endsWith:$)) ifTrue:[ |
617 d := d copyFrom:2 to:(d size - 1). |
673 d := d copyFrom:2 to:(d size - 1). |
618 ^ self convert:howMany from:sourceUnit to:d |
674 ^ self convert:howMany from:sourceUnit to:d pairsAlreadyTried:pairsAlready |
619 ] |
675 ] |
620 ]. |
676 ]. |
621 ]. |
677 ]. |
622 |
678 |
623 "/ first, get rid of scalers ... |
679 "/ first, get rid of scalers ... |
624 |
680 |
625 u := self unscaled:sourceUnit. |
681 u := self unscaled:sourceUnit. |
626 u notNil ifTrue:[ |
682 u notNil ifTrue:[ |
627 ^ self convert:(howMany*(u value)) from:(u key) to:destUnit |
683 ^ self convert:(howMany*(u value)) from:(u key) to:destUnit pairsAlreadyTried:pairsAlready |
628 ]. |
684 ]. |
629 |
685 |
630 u := self unscaled:destUnit. |
686 u := self unscaled:destUnit. |
631 u notNil ifTrue:[ |
687 u notNil ifTrue:[ |
632 ^ self convert:(howMany/(u value)) from:sourceUnit to:(u key) |
688 ^ self convert:(howMany/(u value)) from:sourceUnit to:(u key) pairsAlreadyTried:pairsAlready |
633 ]. |
689 ]. |
634 |
690 |
635 "/ and of aliases ... |
691 "/ and of aliases ... |
636 |
692 |
637 alias := Aliases at:sourceUnit ifAbsent:nil. |
693 alias := Aliases at:sourceUnit ifAbsent:nil. |
638 alias notNil ifTrue:[ |
694 alias notNil ifTrue:[ |
639 ^ self convert:howMany from:alias to:destUnit |
695 ^ self convert:howMany from:alias to:destUnit pairsAlreadyTried:pairsAlready |
640 ]. |
696 ]. |
641 alias := Aliases at:destUnit ifAbsent:nil. |
697 alias := Aliases at:destUnit ifAbsent:nil. |
642 alias notNil ifTrue:[ |
698 alias notNil ifTrue:[ |
643 ^ self convert:howMany from:sourceUnit to:alias |
699 ^ self convert:howMany from:sourceUnit to:alias pairsAlreadyTried:pairsAlready |
644 ]. |
700 ]. |
645 |
701 |
646 "/ any constants ? |
702 "/ any constants ? |
647 |
703 |
648 (Constants includesKey:sourceUnit) ifTrue:[ |
704 (Constants includesKey:sourceUnit) ifTrue:[ |
649 const := Constants at:sourceUnit. |
705 const := Constants at:sourceUnit. |
650 val := const at:1. |
706 val := const at:1. |
651 unit := const at:2. |
707 unit := const at:2. |
652 ^ self convert:(howMany*val) from:unit to:destUnit |
708 ^ self convert:(howMany*val) from:unit to:destUnit pairsAlreadyTried:pairsAlready |
653 ]. |
709 ]. |
654 |
710 |
655 "/ compounds (^ , / or *) are very naively parsed |
711 "/ compounds (^ , / or *) are very naively parsed |
656 "/ need a full expression parser (tree) for full power. |
712 "/ need a full expression parser (tree) for full power. |
657 "/ I leave that as an excercise to you ... |
713 "/ I leave that as an excercise to you ... |
661 |
717 |
662 ((sourceUnit endsWith:'^2') and:[destUnit endsWith:'^2']) ifTrue:[ |
718 ((sourceUnit endsWith:'^2') and:[destUnit endsWith:'^2']) ifTrue:[ |
663 sU := (sourceUnit copyButLast:2) asSymbolIfInterned. |
719 sU := (sourceUnit copyButLast:2) asSymbolIfInterned. |
664 dU := (destUnit copyButLast:2) asSymbolIfInterned. |
720 dU := (destUnit copyButLast:2) asSymbolIfInterned. |
665 (sU notNil and:[dU notNil]) ifTrue:[ |
721 (sU notNil and:[dU notNil]) ifTrue:[ |
666 ^ (self convert:(howMany sqrt) from:sU to:dU) squared |
722 ^ (self convert:(howMany sqrt) from:sU to:dU pairsAlreadyTried:pairsAlready) squared |
667 ]. |
723 ]. |
668 ^ self noConversionFrom:sourceUnit to:destUnit. |
724 ^ self noConversionFrom:sourceUnit to:destUnit. |
669 ]. |
725 ]. |
670 ((sourceUnit endsWith:'^3') and:[destUnit endsWith:'^3']) ifTrue:[ |
726 ((sourceUnit endsWith:'^3') and:[destUnit endsWith:'^3']) ifTrue:[ |
671 sU := (sourceUnit copyButLast:2) asSymbolIfInterned. |
727 sU := (sourceUnit copyButLast:2) asSymbolIfInterned. |
672 dU := (destUnit copyButLast:2) asSymbolIfInterned. |
728 dU := (destUnit copyButLast:2) asSymbolIfInterned. |
673 (sU notNil and:[dU notNil]) ifTrue:[ |
729 (sU notNil and:[dU notNil]) ifTrue:[ |
674 ^ (self convert:(howMany raisedTo:(1/3)) from:sU to:dU) raisedTo:3 |
730 ^ (self convert:(howMany raisedTo:(1/3)) from:sU to:dU pairsAlreadyTried:pairsAlready) raisedTo:3 |
675 ]. |
731 ]. |
676 ^ self noConversionFrom:sourceUnit to:destUnit. |
732 ^ self noConversionFrom:sourceUnit to:destUnit. |
677 ]. |
733 ]. |
678 |
734 |
679 "/ working with fractions ? |
735 "/ working with fractions ? |
721 |
777 |
722 rslt := self convertDirect:howMany from:sourceUnit to:destUnit. |
778 rslt := self convertDirect:howMany from:sourceUnit to:destUnit. |
723 rslt notNil ifTrue:[^ rslt]. |
779 rslt notNil ifTrue:[^ rslt]. |
724 |
780 |
725 "/ try inverse conversion ... |
781 "/ try inverse conversion ... |
726 |
782 "/ but here, only linear factors (numeric conversions) are allowed!! |
727 rslt := self convertDirect:1 from:destUnit to:sourceUnit. |
783 [ |
728 rslt notNil ifTrue:[ ^ howMany / rslt]. |
784 |conversions revFactor| |
729 |
785 |
|
786 conversions := Conversions at:destUnit ifAbsent:nil. |
|
787 conversions notNil ifTrue:[ |
|
788 revFactor := conversions at:sourceUnit ifAbsent:nil. |
|
789 revFactor isNumber ifTrue:[ |
|
790 ^ howMany / revFactor |
|
791 ]. |
|
792 ]. |
|
793 ] value. |
|
794 |
|
795 |
730 "/ here's the deep recursion ... |
796 "/ here's the deep recursion ... |
731 |
797 |
732 |
|
733 "/ try indirect conversion from source |
798 "/ try indirect conversion from source |
734 |
|
735 conversions := Conversions at:sourceUnit ifAbsent:nil. |
799 conversions := Conversions at:sourceUnit ifAbsent:nil. |
736 conversions notNil ifTrue:[ |
800 conversions notNil ifTrue:[ |
737 conversions keysAndValuesDo:[:intermediateUnit :factor1 | |
801 conversions keysAndValuesDo:[:intermediateUnit :factor1 | |
738 |factor2| |
802 |factor2 intermediateValue result| |
739 |
803 |
740 factor2 := self convert:factor1 from:intermediateUnit to:destUnit. |
804 factor1 isBlock ifTrue:[ |
741 factor2 notNil ifTrue:[^ factor2 * howMany]. |
805 intermediateValue := factor1 value:howMany. |
|
806 result := self convert:intermediateValue from:intermediateUnit to:destUnit pairsAlreadyTried:pairsAlready. |
|
807 result notNil ifTrue:[ ^ result ]. |
|
808 ] ifFalse:[ |
|
809 factor2 := self convert:factor1 from:intermediateUnit to:destUnit pairsAlreadyTried:pairsAlready. |
|
810 factor2 notNil ifTrue:[^ factor2 * howMany]. |
|
811 ]. |
742 ]. |
812 ]. |
743 ]. |
813 ]. |
744 |
814 |
745 "/ try indirect conversion from dest |
815 "/ try indirect conversion from dest |
746 |
816 |
747 conversions := Conversions at:destUnit ifAbsent:nil. |
817 conversions := Conversions at:destUnit ifAbsent:nil. |
748 conversions notNil ifTrue:[ |
818 conversions notNil ifTrue:[ |
749 conversions keysAndValuesDo:[:intermediateUnit :factor1 | |
819 conversions keysAndValuesDo:[:intermediateUnit :factor1 | |
750 |factor2| |
820 |factor2| |
751 |
821 |
752 factor2 := self convert:(factor1) from:intermediateUnit to:sourceUnit. |
822 factor1 isBlock ifFalse:[ |
753 factor2 notNil ifTrue:[^ howMany / factor2]. |
823 factor2 := self convert:(factor1) from:intermediateUnit to:sourceUnit pairsAlreadyTried:pairsAlready. |
|
824 factor2 notNil ifTrue:[^ howMany / factor2]. |
|
825 ]. |
754 ]. |
826 ]. |
755 ]. |
827 ]. |
756 |
828 |
757 "/ if working with a product, try each component |
829 "/ if working with a product, try each component |
758 |
830 |
809 |
880 |
810 UnitConverter convert:5 from:#barrel to:#liter |
881 UnitConverter convert:5 from:#barrel to:#liter |
811 UnitConverter convert:10 from:#kilogram to:#carat |
882 UnitConverter convert:10 from:#kilogram to:#carat |
812 |
883 |
813 UnitConverter convert:1 from:#liter to:#floz |
884 UnitConverter convert:1 from:#liter to:#floz |
814 " |
885 UnitConverter convert:0 from:#fahrenheit to:#kelvin |
815 |
886 UnitConverter convert:0 from:#fahrenheit to:#celsius |
816 "Created: 31.5.1996 / 16:23:38 / cg" |
887 UnitConverter convert:0 from:#celsius to:#kelvin |
817 "Modified: 6.8.1997 / 18:10:22 / cg" |
888 UnitConverter convert:0 from:#kelvin to:#celsius |
|
889 " |
|
890 |
|
891 "Created: / 17-09-2017 / 10:11:40 / cg" |
|
892 "Modified: / 18-09-2017 / 08:39:15 / cg" |
818 ! |
893 ! |
819 |
894 |
820 fileSizeBinaryStringFor:nBytes |
895 fileSizeBinaryStringFor:nBytes |
821 "return a useful string for a size-in-bytes in programmer's notation; |
896 "return a useful string for a size-in-bytes in programmer's notation; |
822 Scales by Ki (*1024), Mi (*1024*1024) or Gi (*1024*1024*1024) or even Ti |
897 Scales by Ki (*1024), Mi (*1024*1024) or Gi (*1024*1024*1024) or even Ti |
1324 "Created: 29.3.1997 / 17:56:03 / cg" |
1399 "Created: 29.3.1997 / 17:56:03 / cg" |
1325 ! ! |
1400 ! ! |
1326 |
1401 |
1327 !UnitConverter class methodsFor:'private'! |
1402 !UnitConverter class methodsFor:'private'! |
1328 |
1403 |
1329 addConversion:factor from:sourceMetric to:destMetric |
1404 addConversion:factorOrBlock from:sourceMetric to:destMetric |
1330 "add a conversion" |
1405 "add a conversion" |
1331 |
1406 |
1332 |conversion| |
1407 |conversion| |
1333 |
1408 |
1334 conversion := Conversions at:sourceMetric ifAbsent:nil. |
1409 conversion := Conversions at:sourceMetric ifAbsent:nil. |
1335 conversion isNil ifTrue:[ |
1410 conversion isNil ifTrue:[ |
1336 conversion := IdentityDictionary new. |
1411 conversion := IdentityDictionary new. |
1337 Conversions at:sourceMetric put:conversion |
1412 Conversions at:sourceMetric put:conversion |
1338 ]. |
1413 ]. |
1339 conversion at:destMetric put:factor. |
1414 conversion at:destMetric put:factorOrBlock. |
1340 ^ conversion |
1415 ^ conversion |
1341 |
1416 |
1342 "Created: 31.5.1996 / 13:51:25 / cg" |
1417 "Created: 31.5.1996 / 13:51:25 / cg" |
1343 "Modified: 29.3.1997 / 17:19:31 / cg" |
1418 "Modified: 29.3.1997 / 17:19:31 / cg" |
1344 ! |
1419 ! |