Merge pull request #2628 from Tegiminis/develop

Adding "mult" to traits contrib
This commit is contained in:
Griatch 2022-03-04 19:52:02 +01:00 committed by GitHub
commit 0cd57ad0ed
2 changed files with 201 additions and 124 deletions

View file

@ -286,13 +286,14 @@ class TestTraitStatic(_TraitHandlerBase):
trait_type="static",
base=1,
mod=2,
mult=1.0,
extra_val1="xvalue1",
extra_val2="xvalue2",
)
self.trait = self.traithandler.get("test1")
def _get_values(self):
return self.trait.base, self.trait.mod, self.trait.value
return self.trait.base, self.trait.mod, self.trait.mult, self.trait.value
def test_init(self):
self.assertEqual(
@ -302,25 +303,34 @@ class TestTraitStatic(_TraitHandlerBase):
"trait_type": "static",
"base": 1,
"mod": 2,
"mult": 1.0,
"extra_val1": "xvalue1",
"extra_val2": "xvalue2",
},
)
def test_value(self):
"""value is base + mod"""
self.assertEqual(self._get_values(), (1, 2, 3))
"""value is (base + mod) * mult"""
self.assertEqual(self._get_values(), (1, 2, 1.0, 3))
self.trait.base += 4
self.assertEqual(self._get_values(), (5, 2, 7))
self.assertEqual(self._get_values(), (5, 2, 1.0, 7))
self.trait.mod -= 1
self.assertEqual(self._get_values(), (5, 1, 6))
self.assertEqual(self._get_values(), (5, 1, 1.0, 6))
self.trait.mult += 1.0
self.assertEqual(self._get_values(), (5, 1, 2.0, 12))
self.trait.mult = 0.75
self.assertEqual(self._get_values(), (5, 1, 0.75, 4.5))
def test_delete(self):
"""Deleting resets to default."""
self.trait.mult = 2.0
del self.trait.base
self.assertEqual(self._get_values(), (0, 2, 2))
self.assertEqual(self._get_values(), (0, 2, 2.0, 4))
del self.trait.mult
self.assertEqual(self._get_values(), (0, 2, 1.0, 2))
del self.trait.mod
self.assertEqual(self._get_values(), (0, 0, 0))
self.assertEqual(self._get_values(), (0, 0, 1.0, 0))
class TestTraitCounter(_TraitHandlerBase):
@ -336,6 +346,7 @@ class TestTraitCounter(_TraitHandlerBase):
trait_type="counter",
base=1,
mod=2,
mult=1.0,
min=0,
max=10,
extra_val1="xvalue1",
@ -350,8 +361,8 @@ class TestTraitCounter(_TraitHandlerBase):
self.trait = self.traithandler.get("test1")
def _get_values(self):
"""Get (base, mod, value, min, max)."""
return (self.trait.base, self.trait.mod, self.trait.value, self.trait.min, self.trait.max)
"""Get (base, mod, mult, value, min, max)."""
return (self.trait.base, self.trait.mod, self.trait.mult, self.trait.value, self.trait.min, self.trait.max)
def test_init(self):
self.assertEqual(
@ -361,6 +372,7 @@ class TestTraitCounter(_TraitHandlerBase):
"trait_type": "counter",
"base": 1,
"mod": 2,
"mult": 1.0,
"min": 0,
"max": 10,
"extra_val1": "xvalue1",
@ -378,102 +390,105 @@ class TestTraitCounter(_TraitHandlerBase):
)
def test_value(self):
"""value is current + mod, where current defaults to base"""
self.assertEqual(self._get_values(), (1, 2, 3, 0, 10))
"""value is (current + mod) * mult, where current defaults to base"""
self.assertEqual(self._get_values(), (1, 2, 1.0, 3, 0, 10))
self.trait.base += 4
self.assertEqual(self._get_values(), (5, 2, 7, 0, 10))
self.assertEqual(self._get_values(), (5, 2, 1.0, 7, 0, 10))
self.trait.mod -= 1
self.assertEqual(self._get_values(), (5, 1, 6, 0, 10))
self.assertEqual(self._get_values(), (5, 1, 1.0, 6, 0, 10))
self.trait.mult += 1.0
self.assertEqual(self._get_values(), (5, 1, 2.0, 10, 0, 10))
def test_boundaries__minmax(self):
"""Test range"""
# should not exceed min/max values
self.trait.base += 20
self.assertEqual(self._get_values(), (8, 2, 10, 0, 10))
self.assertEqual(self._get_values(), (8, 2, 1.0, 10, 0, 10))
self.trait.base = 100
self.assertEqual(self._get_values(), (8, 2, 10, 0, 10))
self.assertEqual(self._get_values(), (8, 2, 1.0, 10, 0, 10))
self.trait.base -= 40
self.assertEqual(self._get_values(), (-2, 2, 0, 0, 10))
self.assertEqual(self._get_values(), (-2, 2, 1.0, 0, 0, 10))
self.trait.base = -100
self.assertEqual(self._get_values(), (-2, 2, 0, 0, 10))
self.assertEqual(self._get_values(), (-2, 2, 1.0, 0, 0, 10))
def test_boundaries__bigmod(self):
"""add a big mod"""
self.trait.base = 5
self.trait.mod = 100
self.assertEqual(self._get_values(), (5, 5, 10, 0, 10))
self.assertEqual(self._get_values(), (5, 5, 1.0, 10, 0, 10))
self.trait.mod = -100
self.assertEqual(self._get_values(), (5, -5, 0, 0, 10))
self.assertEqual(self._get_values(), (5, -5, 1.0, 0, 0, 10))
def test_boundaries__change_boundaries(self):
"""Change boundaries after base/mod change"""
self.trait.base = 5
self.trait.mod = -100
self.trait.min = -20
self.assertEqual(self._get_values(), (5, -5, 0, -20, 10))
self.assertEqual(self._get_values(), (5, -5, 1.0, 0, -20, 10))
self.trait.mod -= 100
self.assertEqual(self._get_values(), (5, -25, -20, -20, 10))
self.assertEqual(self._get_values(), (5, -25, 1.0, -20, -20, 10))
self.trait.mod = 100
self.trait.max = 20
self.assertEqual(self._get_values(), (5, 5, 10, -20, 20))
self.assertEqual(self._get_values(), (5, 5, 1.0, 10, -20, 20))
self.trait.mod = 100
self.assertEqual(self._get_values(), (5, 15, 20, -20, 20))
self.assertEqual(self._get_values(), (5, 15, 1.0, 20, -20, 20))
def test_boundaries__disable(self):
"""Disable and re-enable boundaries"""
self.trait.base = 5
self.trait.mod = 100
self.assertEqual(self._get_values(), (5, 5, 10, 0, 10))
self.assertEqual(self._get_values(), (5, 5, 1.0, 10, 0, 10))
del self.trait.max
self.assertEqual(self.trait.max, None)
del self.trait.min
self.assertEqual(self.trait.min, None)
self.trait.base = 100
self.assertEqual(self._get_values(), (100, 5, 105, None, None))
self.assertEqual(self._get_values(), (100, 5, 1.0, 105, None, None))
self.trait.base = -200
self.assertEqual(self._get_values(), (-200, 5, -195, None, None))
self.assertEqual(self._get_values(), (-200, 5, 1.0, -195, None, None))
# re-activate boundaries
self.trait.max = 15
self.trait.min = 10 # his is blocked since base+mod is lower
self.assertEqual(self._get_values(), (-200, 5, -195, -195, 15))
self.assertEqual(self._get_values(), (-200, 5, 1.0, -195, -195, 15))
def test_boundaries__inverse(self):
"""Set inverse boundaries - limited by base"""
self.trait.mod = 0
self.assertEqual(self._get_values(), (1, 0, 1, 0, 10))
self.assertEqual(self._get_values(), (1, 0, 1.0, 1, 0, 10))
self.trait.min = 20 # will be set to base
self.assertEqual(self._get_values(), (1, 0, 1, 1, 10))
self.assertEqual(self._get_values(), (1, 0, 1.0, 1, 1, 10))
self.trait.max = -20
self.assertEqual(self._get_values(), (1, 0, 1, 1, 1))
self.assertEqual(self._get_values(), (1, 0, 1.0, 1, 1, 1))
def test_current(self):
"""Modifying current value"""
self.trait.current = 5
self.assertEqual(self._get_values(), (1, 2, 7, 0, 10))
self.assertEqual(self._get_values(), (1, 2, 1.0, 7, 0, 10))
self.trait.current = 10
self.assertEqual(self._get_values(), (1, 2, 10, 0, 10))
self.assertEqual(self._get_values(), (1, 2, 1.0, 10, 0, 10))
self.trait.current = 12
self.assertEqual(self._get_values(), (1, 2, 10, 0, 10))
self.assertEqual(self._get_values(), (1, 2, 1.0, 10, 0, 10))
self.trait.current = -1
self.assertEqual(self._get_values(), (1, 2, 2, 0, 10))
self.assertEqual(self._get_values(), (1, 2, 1.0, 2, 0, 10))
self.trait.current -= 10
self.assertEqual(self._get_values(), (1, 2, 2, 0, 10))
self.assertEqual(self._get_values(), (1, 2, 1.0, 2, 0, 10))
def test_delete(self):
"""Deleting resets to default."""
del self.trait.base
self.assertEqual(self._get_values(), (0, 2, 2, 0, 10))
self.assertEqual(self._get_values(), (0, 2, 1.0, 2, 0, 10))
del self.trait.mod
self.assertEqual(self._get_values(), (0, 0, 0, 0, 10))
self.assertEqual(self._get_values(), (0, 0, 1.0, 0, 0, 10))
del self.trait.min
del self.trait.max
self.assertEqual(self._get_values(), (0, 0, 0, None, None))
self.assertEqual(self._get_values(), (0, 0, 1.0, 0, None, None))
def test_percentage(self):
"""Test percentage calculation"""
self.trait.base = 8
self.trait.mod = 2
self.trait.mult = 1.0
self.trait.min = 0
self.trait.max = 10
self.assertEqual(self.trait.percent(), "100.0%")
@ -494,7 +509,7 @@ class TestTraitCounter(_TraitHandlerBase):
"""Test descriptions"""
self.trait.min = -5
self.trait.mod = 0
self.assertEqual(self._get_values(), (1, 0, 1, -5, 10))
self.assertEqual(self._get_values(), (1, 0, 1.0, 1, -5, 10))
self.trait.current = -2
self.assertEqual(self.trait.desc(), "range0")
self.trait.current = 0
@ -525,6 +540,7 @@ class TestTraitCounterTimed(_TraitHandlerBase):
trait_type="counter",
base=1,
mod=2,
mult=1.0,
min=0,
max=100,
extra_val1="xvalue1",
@ -602,8 +618,9 @@ class TestTraitGauge(_TraitHandlerBase):
"test1",
name="Test1",
trait_type="gauge",
base=8, # max = base + mod
base=8, # max = (base + mod) * mult
mod=2,
mult=1.0,
extra_val1="xvalue1",
extra_val2="xvalue2",
descs={
@ -617,7 +634,7 @@ class TestTraitGauge(_TraitHandlerBase):
def _get_values(self):
"""Get (base, mod, value, min, max)."""
return (self.trait.base, self.trait.mod, self.trait.value, self.trait.min, self.trait.max)
return (self.trait.base, self.trait.mod, self.trait.mult, self.trait.value, self.trait.min, self.trait.max)
def test_init(self):
self.assertEqual(
@ -627,6 +644,7 @@ class TestTraitGauge(_TraitHandlerBase):
"trait_type": "gauge",
"base": 8,
"mod": 2,
"mult": 1.0,
"min": 0,
"extra_val1": "xvalue1",
"extra_val2": "xvalue2",
@ -645,71 +663,80 @@ class TestTraitGauge(_TraitHandlerBase):
def test_value(self):
"""value is current, where current defaults to base + mod"""
# current unset - follows base + mod
self.assertEqual(self._get_values(), (8, 2, 10, 0, 10))
self.assertEqual(self._get_values(), (8, 2, 1.0, 10, 0, 10))
self.trait.base += 4
self.assertEqual(self._get_values(), (12, 2, 14, 0, 14))
self.assertEqual(self._get_values(), (12, 2, 1.0, 14, 0, 14))
self.trait.mod -= 1
self.assertEqual(self._get_values(), (12, 1, 13, 0, 13))
self.assertEqual(self._get_values(), (12, 1, 1.0, 13, 0, 13))
self.trait.mult += 1.0
self.assertEqual(self._get_values(), (12, 1, 2.0, 26, 0, 26))
# set current, decouple from base + mod
self.trait.current = 5
self.assertEqual(self._get_values(), (12, 1, 5, 0, 13))
self.assertEqual(self._get_values(), (12, 1, 2.0, 5, 0, 26))
self.trait.mod += 1
self.trait.base -= 4
self.assertEqual(self._get_values(), (8, 2, 5, 0, 10))
self.trait.mult -= 1.0
self.assertEqual(self._get_values(), (8, 2, 1.0, 5, 0, 10))
self.trait.min = -100
self.trait.base = -20
self.assertEqual(self._get_values(), (-20, 2, -18, -100, -18))
self.assertEqual(self._get_values(), (-20, 2, 1.0, -18, -100, -18))
def test_boundaries__minmax(self):
"""Test range"""
# current unset - tied to base + mod
self.trait.base += 20
self.assertEqual(self._get_values(), (28, 2, 30, 0, 30))
self.assertEqual(self._get_values(), (28, 2, 1.0, 30, 0, 30))
# set current - decouple from base + mod
self.trait.current = 19
self.assertEqual(self._get_values(), (28, 2, 19, 0, 30))
self.assertEqual(self._get_values(), (28, 2, 1.0, 19, 0, 30))
# test upper bound
self.trait.current = 100
self.assertEqual(self._get_values(), (28, 2, 30, 0, 30))
self.assertEqual(self._get_values(), (28, 2, 1.0, 30, 0, 30))
# with multiplier
self.trait.mult = 2.0
self.assertEqual(self._get_values(), (28, 2, 2.0, 30, 0, 60))
self.trait.current = 100
self.assertEqual(self._get_values(), (28, 2, 2.0, 60, 0, 60))
# min defaults to 0
self.trait.mult = 1.0
self.trait.current = -10
self.assertEqual(self._get_values(), (28, 2, 0, 0, 30))
self.assertEqual(self._get_values(), (28, 2, 1.0, 0, 0, 30))
self.trait.min = -20
self.assertEqual(self._get_values(), (28, 2, 0, -20, 30))
self.assertEqual(self._get_values(), (28, 2, 1.0, 0, -20, 30))
self.trait.current = -10
self.assertEqual(self._get_values(), (28, 2, -10, -20, 30))
self.assertEqual(self._get_values(), (28, 2, 1.0, -10, -20, 30))
def test_boundaries__bigmod(self):
"""add a big mod"""
self.trait.base = 5
self.trait.mod = 100
self.assertEqual(self._get_values(), (5, 100, 105, 0, 105))
self.assertEqual(self._get_values(), (5, 100, 1.0, 105, 0, 105))
# restricted by min
self.trait.mod = -100
self.assertEqual(self._get_values(), (5, -5, 0, 0, 0))
self.assertEqual(self._get_values(), (5, -5, 1.0, 0, 0, 0))
self.trait.min = -200
self.assertEqual(self._get_values(), (5, -5, 0, -200, 0))
self.assertEqual(self._get_values(), (5, -5, 1.0, 0, -200, 0))
def test_boundaries__change_boundaries(self):
"""Change boundaries after current change"""
self.trait.current = 20
self.assertEqual(self._get_values(), (8, 2, 10, 0, 10))
self.assertEqual(self._get_values(), (8, 2, 1.0, 10, 0, 10))
self.trait.mod = 102
self.assertEqual(self._get_values(), (8, 102, 10, 0, 110))
self.assertEqual(self._get_values(), (8, 102, 1.0, 10, 0, 110))
# raising min past current value will force it upwards
self.trait.min = 20
self.assertEqual(self._get_values(), (8, 102, 20, 20, 110))
self.assertEqual(self._get_values(), (8, 102, 1.0, 20, 20, 110))
def test_boundaries__disable(self):
"""Disable and re-enable boundary"""
self.trait.base = 5
self.trait.min = 1
self.assertEqual(self._get_values(), (5, 2, 7, 1, 7))
self.assertEqual(self._get_values(), (5, 2, 1.0, 7, 1, 7))
del self.trait.min
self.assertEqual(self._get_values(), (5, 2, 7, 0, 7))
self.assertEqual(self._get_values(), (5, 2, 1.0, 7, 0, 7))
del self.trait.base
del self.trait.mod
self.assertEqual(self._get_values(), (0, 0, 0, 0, 0))
self.assertEqual(self._get_values(), (0, 0, 1.0, 0, 0, 0))
with self.assertRaises(traits.TraitException):
del self.trait.max
@ -717,39 +744,39 @@ class TestTraitGauge(_TraitHandlerBase):
"""Try to set reversed boundaries"""
self.trait.mod = 0
self.trait.base = -10 # limited by min
self.assertEqual(self._get_values(), (0, 0, 0, 0, 0))
self.assertEqual(self._get_values(), (0, 0, 1.0, 0, 0, 0))
self.trait.min = -10
self.assertEqual(self._get_values(), (0, 0, 0, -10, 0))
self.assertEqual(self._get_values(), (0, 0, 1.0, 0, -10, 0))
self.trait.base = -10
self.assertEqual(self._get_values(), (-10, 0, -10, -10, -10))
self.assertEqual(self._get_values(), (-10, 0, 1.0, -10, -10, -10))
self.min = 0 # limited by base + mod
self.assertEqual(self._get_values(), (-10, 0, -10, -10, -10))
self.assertEqual(self._get_values(), (-10, 0, 1.0, -10, -10, -10))
def test_current(self):
"""Modifying current value"""
self.trait.base = 10
self.trait.current = 5
self.assertEqual(self._get_values(), (10, 2, 5, 0, 12))
self.assertEqual(self._get_values(), (10, 2, 1.0, 5, 0, 12))
self.trait.current = 10
self.assertEqual(self._get_values(), (10, 2, 10, 0, 12))
self.assertEqual(self._get_values(), (10, 2, 1.0, 10, 0, 12))
self.trait.current = 12
self.assertEqual(self._get_values(), (10, 2, 12, 0, 12))
self.assertEqual(self._get_values(), (10, 2, 1.0, 12, 0, 12))
self.trait.current = 0
self.assertEqual(self._get_values(), (10, 2, 0, 0, 12))
self.assertEqual(self._get_values(), (10, 2, 1.0, 0, 0, 12))
self.trait.current = -1
self.assertEqual(self._get_values(), (10, 2, 0, 0, 12))
self.assertEqual(self._get_values(), (10, 2, 1.0, 0, 0, 12))
def test_delete(self):
"""Deleting resets to default."""
del self.trait.mod
self.assertEqual(self._get_values(), (8, 0, 8, 0, 8))
self.assertEqual(self._get_values(), (8, 0, 1.0, 8, 0, 8))
self.trait.mod = 2
del self.trait.base
self.assertEqual(self._get_values(), (0, 2, 2, 0, 2))
self.assertEqual(self._get_values(), (0, 2, 1.0, 2, 0, 2))
del self.trait.min
self.assertEqual(self._get_values(), (0, 2, 2, 0, 2))
self.assertEqual(self._get_values(), (0, 2, 1.0, 2, 0, 2))
self.trait.min = -10
self.assertEqual(self._get_values(), (0, 2, 2, -10, 2))
self.assertEqual(self._get_values(), (0, 2, 1.0, 2, -10, 2))
del self.trait.min
self.assertEqual(self._get_values(), (0, 2, 2, 0, 2))

View file

@ -45,7 +45,7 @@ class Character(DefaultCharacter):
def at_object_creation(self):
# (or wherever you want)
self.traits.add("str", "Strength", trait_type="static", base=10, mod=2)
self.traits.add("str", "Strength", trait_type="static", base=10, mod=2, mult=2.0)
self.traits.add("hp", "Health", trait_type="gauge", min=0, max=100)
self.traits.add("hunting", "Hunting Skill", trait_type="counter",
base=10, mod=1, min=0, max=100)
@ -74,9 +74,9 @@ from evennia.contrib.rpg.traits import TraitProperty
class Object(DefaultObject):
...
strength = TraitProperty("Strength", trait_type="static", base=10, mod=2)
strength = TraitProperty("Strength", trait_type="static", base=10, mod=2, mult=1.5)
health = TraitProperty("Health", trait_type="gauge", min=0, base=100, mod=2)
hunting = TraitProperty("Hunting Skill", trait_type="counter", base=10, mod=1, min=0, max=100)
hunting = TraitProperty("Hunting Skill", trait_type="counter", base=10, mod=1, mult=2.0, min=0, max=100)
```
@ -102,14 +102,14 @@ each other depends on the trait type.
```python
> obj.traits.strength.value
12 # base + mod
18 # (base + mod) * mult
> obj.traits.strength.base += 5
> obj.traits.strength.base += 6
obj.traits.strength.value
17
27
> obj.traits.hp.value
102 # base + mod
102 # (base + mod) * mult
> obj.traits.hp.base -= 200
> obj.traits.hp.value
@ -131,11 +131,11 @@ obj.traits.strength.value
# with TraitProperties:
> obj.hunting.value
12
22
> obj.strength.value += 5
> obj.strength.value
17
32
```
@ -171,25 +171,27 @@ if trait1 > trait2:
```
## Static trait
`value = base + mod`
`value = (base + mod) * mult`
The static trait has a `base` value and an optional `mod`-ifier. A typical use
of a static trait would be a Strength stat or Skill value. That is, something
that varies slowly or not at all, and which may be modified in-place.
The static trait has a `base` value and an optional `mod`-ifier and 'mult'-iplier.
The modifier defaults to 0, and the multiplier to 1.0, for no change in value.
A typical use of a static trait would be a Strength stat or Skill value. That is,
somethingthat varies slowly or not at all, and which may be modified in-place.
```python
> obj.traits.add("str", "Strength", trait_type="static", base=10, mod=2)
> obj.traits.mytrait.value
12 # base + mod
> obj.traits.mytrait.base += 2
> obj.traits.mytrait.mod += 1
> obj.traits.mytrait.value
15
> obj.traits.mytrait.mod = 0
> obj.traits.mytrait.mult = 2.0
> obj.traits.mytrait.value
12
20
```
@ -199,18 +201,20 @@ that varies slowly or not at all, and which may be modified in-place.
min/unset base base+mod max/unset
|--------------|--------|---------X--------X------------|
current value
= current
+ mod
= (current
+ mod)
* mult
A counter describes a value that can move from a base. The `.current` property
is the thing usually modified. It starts at the `.base`. One can also add a
modifier, which will both be added to the base and to current (forming
`.value`). The min/max of the range are optional, a boundary set to None will
remove it. A suggested use for a Counter Trait would be to track skill values.
modifier, which is added to both the base and to current. '.value' is then formed
by multiplying by the multiplier, which defaults to 1.0 for no change. The min/max
of the range are optional, a boundary set to None will remove it. A suggested use
for a Counter Trait would be to track skill values.
```python
> obj.traits.add("hunting", "Hunting Skill", trait_type="counter",
base=10, mod=1, min=0, max=100)
base=10, mod=1, mult=1.0, min=0, max=100)
> obj.traits.hunting.value
11 # current starts at base + mod
@ -222,7 +226,10 @@ remove it. A suggested use for a Counter Trait would be to track skill values.
> del obj.traits.hunting.current
> obj.traits.hunting.value
11
> obj.traits.hunting.max = None # removing upper bound
> obj.traits.hunting.mult = 100.0
1100
# for TraitProperties, pass the args/kwargs of traits.add() to the
# TraitProperty constructor instead.
@ -1141,20 +1148,20 @@ class Trait:
class StaticTrait(Trait):
"""
Static Trait. This is a single value with a modifier,
with no concept of a 'current' value or min/max etc.
Static Trait. This is a single value with a modifier,
multiplier, and no concept of a 'current' value or min/max etc.
value = base + mod
value = (base + mod) * mult
"""
trait_type = "static"
default_keys = {"base": 0, "mod": 0}
default_keys = {"base": 0, "mod": 0, "mult": 1.0}
def __str__(self):
status = "{value:11}".format(value=self.value)
return "{name:12} {status} ({mod:+3})".format(name=self.name, status=status, mod=self.mod)
return "{name:12} {status} ({mod:+3}) (* {mult:.2f})".format(name=self.name, status=status, mod=self.mod, mult=self.mult)
# Helpers
@property
@ -1178,10 +1185,24 @@ class StaticTrait(Trait):
if type(amount) in (int, float):
self._data["mod"] = amount
@property
def mult(self):
"""The trait's multiplier."""
return self._data["mult"]
@mult.setter
def mult(self, amount):
if type(amount) in (int, float):
self._data["mult"] = amount
@mult.deleter
def mult(self):
self._data["mult"] = 1.0
@property
def value(self):
"The value of the Trait"
return self.base + self.mod
"The value of the Trait."
return (self.base + self.mod) * self.mult
class CounterTrait(Trait):
@ -1191,13 +1212,14 @@ class CounterTrait(Trait):
This includes modifications and min/max limits as well as the notion of a
current value. The value can also be reset to the base value.
min/unset base base+mod max/unset
min/unset base (base+mod)*mult max/unset
|--------------|--------|---------X--------X------------|
current value
= current
+ mod
= (current
+ mod)
* mult
- value = current + mod, starts at base + mod
- value = (current + mod) * mult, starts at (base + mod) * mult
- if min or max is None, there is no upper/lower bound (default)
- if max is set to "base", max will be equal ot base+mod
- descs are used to optionally describe each value interval.
@ -1224,6 +1246,7 @@ class CounterTrait(Trait):
default_keys = {
"base": 0,
"mod": 0,
"mult": 1.0,
"min": None,
"max": None,
"descs": None,
@ -1299,16 +1322,16 @@ class CounterTrait(Trait):
now = time()
tdiff = now - self._data["last_update"]
current += rate * tdiff
value = current + self.mod
value = (current + self.mod)
# we must make sure so we don't overstep our bounds
# even if .mod is included
if self._passed_ratetarget(value):
current = self._data["ratetarget"] - self.mod
current = (self._data["ratetarget"] - self.mod)
self._stop_timer()
elif not self._within_boundaries(value):
current = self._enforce_boundaries(value) - self.mod
current = (self._enforce_boundaries(value) - self.mod)
self._stop_timer()
else:
self._data["last_update"] = now
@ -1352,6 +1375,19 @@ class CounterTrait(Trait):
value = self.max - self.base
self._data["mod"] = value
@property
def mult(self):
return self._data["mult"]
@mult.setter
def mult(self, amount):
if type(amount) in (int, float):
self._data["mult"] = amount
@mult.deleter
def mult(self):
self._data["mult"] = 1.0
@property
def min(self):
return self._data["min"]
@ -1382,7 +1418,7 @@ class CounterTrait(Trait):
@property
def current(self):
"""The `current` value of the `Trait`. This does not have .mod added."""
"""The `current` value of the `Trait`. This does not have .mod added and is not .mult-iplied."""
return self._update_current(self._data.get("current", self.base))
@current.setter
@ -1397,8 +1433,8 @@ class CounterTrait(Trait):
@property
def value(self):
"The value of the Trait (current + mod)"
return self._enforce_boundaries(self.current + self.mod)
"The value of the Trait. (current + mod) * mult"
return self._enforce_boundaries((self.current + self.mod) * self.mult)
@property
def ratetarget(self):
@ -1461,15 +1497,15 @@ class GaugeTrait(CounterTrait):
"""
Gauge Trait.
This emulates a gauge-meter that empties from a base+mod value.
This emulates a gauge-meter that empties from a (base+mod) * mult value.
min/0 max=base+mod
min/0 max=(base+mod)*mult
|-----------------------X---------------------------|
value
= current
- min defaults to 0
- max value is always base + mad
- max value is always (base + mod) * mult
- .max is an alias of .base
- value = current and varies from min to max.
- descs is a mapping {upper_bound_inclusive: desc}. These
@ -1493,6 +1529,7 @@ class GaugeTrait(CounterTrait):
default_keys = {
"base": 0,
"mod": 0,
"mult": 1.0,
"min": 0,
"descs": None,
"rate": 0,
@ -1530,11 +1567,11 @@ class GaugeTrait(CounterTrait):
"""Ensures that incoming value falls within trait's range."""
if self.min is not None and value <= self.min:
return self.min
return min(self.mod + self.base, value)
return min((self.mod + self.base) * self.mult, value)
def __str__(self):
status = "{value:4} / {base:4}".format(value=self.value, base=self.base)
return "{name:12} {status} ({mod:+3})".format(name=self.name, status=status, mod=self.mod)
return "{name:12} {status} ({mod:+3}) (* {mult:.2f})".format(name=self.name, status=status, mod=self.mod, mult=self.mult)
@property
def base(self):
@ -1559,6 +1596,19 @@ class GaugeTrait(CounterTrait):
if value + self.base < self.min:
value = self.min - self.base
self._data["mod"] = value
@property
def mult(self):
return self._data["mult"]
@mult.setter
def mult(self, amount):
if type(amount) in (int, float):
self._data["mult"] = amount
@mult.deleter
def mult(self):
self._data["mult"] = 1.0
@property
def min(self):
@ -1567,16 +1617,16 @@ class GaugeTrait(CounterTrait):
@min.setter
def min(self, value):
"""Limit so min can never be greater than base+mod."""
"""Limit so min can never be greater than (base+mod)*mult."""
if value is None:
self._data["min"] = self.default_keys["min"]
elif type(value) in (int, float):
self._data["min"] = min(value, self.base + self.mod)
self._data["min"] = min(value, (self.base + self.mod) * self.mult)
@property
def max(self):
"The max is always base + mod."
return self.base + self.mod
"The max is always (base + mod) * mult."
return (self.base + self.mod) * self.mult
@max.setter
def max(self, value):
@ -1594,7 +1644,7 @@ class GaugeTrait(CounterTrait):
def current(self):
"""The `current` value of the gauge."""
return self._update_current(
self._enforce_boundaries(self._data.get("current", self.base + self.mod))
self._enforce_boundaries(self._data.get("current", (self.base + self.mod) * self.mult))
)
@current.setter
@ -1605,7 +1655,7 @@ class GaugeTrait(CounterTrait):
@current.deleter
def current(self):
"Resets current back to 'full'"
self._data["current"] = self.base + self.mod
self._data["current"] = (self.base + self.mod) * self.mult
@property
def value(self):