mirror of
https://github.com/evennia/evennia.git
synced 2026-03-27 10:16:32 +01:00
Start to add timer component
This commit is contained in:
parent
5e2bbedd52
commit
175fcce405
2 changed files with 53 additions and 427 deletions
|
|
@ -430,7 +430,9 @@ class TestTraitCounter(_TraitHandlerBase):
|
|||
2: "range1",
|
||||
5: "range2",
|
||||
7: "range3",
|
||||
}
|
||||
},
|
||||
"rate": 0,
|
||||
"ratetarget": None,
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -609,7 +611,9 @@ class TestTraitGauge(_TraitHandlerBase):
|
|||
2: "range1",
|
||||
5: "range2",
|
||||
7: "range3",
|
||||
}
|
||||
},
|
||||
"rate": 0,
|
||||
"ratetarget": None,
|
||||
}
|
||||
)
|
||||
def test_actual(self):
|
||||
|
|
@ -834,410 +838,3 @@ class TestNumericTraitOperators(TestCase):
|
|||
self.assertGreaterEqual(8, self.st)
|
||||
self.assertGreaterEqual(self.st, 0)
|
||||
self.assertGreaterEqual(10, self.st)
|
||||
|
||||
|
||||
#
|
||||
#
|
||||
# class TraitTestCase(TestCase):
|
||||
# """Test case for basic Trait functionality."""
|
||||
# def setUp(self):
|
||||
# # direct instantiation for testing only; use TraitHandler in production
|
||||
# self.trait = TraitStatic({
|
||||
# 'trait_type': 'static',
|
||||
# 'name': 'Strength',
|
||||
# 'base': 8,
|
||||
# 'mod': 0,
|
||||
# })
|
||||
#
|
||||
# def tearDown(self):
|
||||
# self.trait = None
|
||||
#
|
||||
# def check_trait(self, base=None, mod=None, actual=None):
|
||||
# """helper; allows one-line checking of `Trait` properties"""
|
||||
# if base is not None: self.assertEqual(self.trait.base, base)
|
||||
# if mod is not None: self.assertEqual(self.trait.mod, mod)
|
||||
# if actual is not None: self.assertEqual(self.trait.actual, actual)
|
||||
#
|
||||
# def test_initial_state(self):
|
||||
# """`Trait` fixture object properties are as expected"""
|
||||
# self.assertEqual(self.trait.name, 'Strength')
|
||||
# self.check_trait(8, 0, 8)
|
||||
#
|
||||
# def test_change_base(self):
|
||||
# """changes to `base` are reflected in `actual`"""
|
||||
# self.trait.base += 1
|
||||
# self.check_trait(9, 0, 9)
|
||||
#
|
||||
# def test_change_mod(self):
|
||||
# """changes to `mod` are reflected in `actual`"""
|
||||
# self.trait.mod = 1
|
||||
# self.check_trait(8, 1, 9)
|
||||
#
|
||||
# def test_reset_mod(self):
|
||||
# """`reset_mod()` function zeroes out `mod`"""
|
||||
# self.mod = 1
|
||||
# self.trait.reset_mod()
|
||||
# self.check_trait(8, 0, 8)
|
||||
#
|
||||
#
|
||||
# class TraitExtraPropsTestCase(TestCase):
|
||||
# """Test case for Trait extra properties functionality."""
|
||||
# def setUp(self):
|
||||
# # direct instantiation for testing only; use TraitHandler in production
|
||||
# self.trait = Trait({
|
||||
# 'type': 'static',
|
||||
# 'name': 'Strength',
|
||||
# 'base': 8,
|
||||
# 'mod': 0,
|
||||
# 'extra': {'preloaded': True},
|
||||
# })
|
||||
#
|
||||
# def tearDown(self):
|
||||
# self.trait = None
|
||||
#
|
||||
# def test_extra_props_get(self):
|
||||
# """test that extra properties are gettable"""
|
||||
# # access via getattr
|
||||
# self.assertTrue(self.trait.preloaded)
|
||||
# # access via getitem
|
||||
# self.assertTrue(self.trait['preloaded'])
|
||||
#
|
||||
# def test_extra_props_set(self):
|
||||
# """test that extra properties are settable"""
|
||||
# # set via setattr
|
||||
# self.trait.skill_points = 2
|
||||
# self.assertIn('skill_points', self.trait.extra)
|
||||
# # set via setitem
|
||||
# self.trait['skill_points'] = 2
|
||||
# self.assertIn('skill_points', self.trait.extra)
|
||||
#
|
||||
# def test_extra_props_del(self):
|
||||
# """test that extra properties are deletable"""
|
||||
# # delete via delattr
|
||||
# del self.trait.preloaded
|
||||
# self.assertNotIn('preloaded', self.trait.extra)
|
||||
# with self.assertRaises(AttributeError):
|
||||
# x = self.trait.preloaded
|
||||
# # delete via delitem
|
||||
# del self.trait['preloaded']
|
||||
# self.assertNotIn('preloaded', self.trait.extra)
|
||||
# with self.assertRaises(KeyError):
|
||||
# x = self.trait['preloaded']
|
||||
#
|
||||
#
|
||||
#
|
||||
# class CounterTraitTestCase(TestCase):
|
||||
# """Test case for counter trait functionality."""
|
||||
# def setUp(self):
|
||||
# # direct instantiation for testing only; use TraitHandler in production
|
||||
# self.trait = Trait({
|
||||
# 'type': 'counter',
|
||||
# 'name': 'Bonus/Penalty',
|
||||
# 'base': 0,
|
||||
# 'mod': 0,
|
||||
# 'min': -3,
|
||||
# 'max': 3,
|
||||
# })
|
||||
#
|
||||
# def tearDown(self):
|
||||
# self.trait = None
|
||||
#
|
||||
# def check_trait(self, base=None, mod=None, current=None,
|
||||
# actual=None, min=None, max=None,):
|
||||
# """helper; allows one-line checking of Trait properties"""
|
||||
# if base is not None: self.assertEqual(self.trait.base, base)
|
||||
# if mod is not None: self.assertEqual(self.trait.mod, mod)
|
||||
# if current is not None: self.assertEqual(self.trait.current, current)
|
||||
# if actual is not None: self.assertEqual(self.trait.actual, actual)
|
||||
# if min is not None: self.assertEqual(self.trait.min, min)
|
||||
# if max is not None: self.assertEqual(self.trait.max, max)
|
||||
#
|
||||
# def test_initial_state(self):
|
||||
# """fixture object properties are as expected"""
|
||||
# self.assertEqual(self.trait.name, 'Bonus/Penalty')
|
||||
# self.check_trait(0, 0, 0, 0, -3, 3)
|
||||
#
|
||||
# def test_upper_bound(self):
|
||||
# """`current` may not be set above `max` when `max` is numeric"""
|
||||
# self.trait.current = 5
|
||||
# self.check_trait(0, 0, 3, 3, -3, 3)
|
||||
#
|
||||
# def test_upper_unbound(self):
|
||||
# """`current` may be set very high when `max` is None"""
|
||||
# self.trait.max = None
|
||||
# self.trait.current = 10000000
|
||||
# self.check_trait(0, 0, 10000000, 10000000, -3, None)
|
||||
#
|
||||
# def test_lower_bound(self):
|
||||
# """`current` may not be set below `min` when `min` is numeric"""
|
||||
# self.trait.current = -5
|
||||
# self.check_trait(0, 0, -3, -3, -3, 3)
|
||||
#
|
||||
# def test_lower_unbound(self):
|
||||
# """`current` may be set very low when `min` is None"""
|
||||
# self.trait.min = None
|
||||
# self.trait.current = -10000000
|
||||
# self.check_trait(0, 0, -10000000, -10000000, None, 3)
|
||||
#
|
||||
# def test_mod(self):
|
||||
# """confirm `mod` functionality mid-range"""
|
||||
# self.trait.mod = 2
|
||||
# self.check_trait(0, 2, 0, 2, -3, 3)
|
||||
#
|
||||
# def test_mod_upper_bound(self):
|
||||
# """`actual` is constrained even if `current`+`mod` exceed `max`"""
|
||||
# self.trait.current = 2
|
||||
# self.trait.mod = 4
|
||||
# self.check_trait(0, 4, 2, 3, -3, 3)
|
||||
#
|
||||
# def test_mod_lower_bound(self):
|
||||
# """`actual` is constrained even if `current`+`mod` exceeds `min`"""
|
||||
# self.trait.current = -2
|
||||
# self.trait.mod = -4
|
||||
# self.check_trait(0, -4, -2, -3, -3, 3)
|
||||
#
|
||||
# def test_no_max_below_base(self):
|
||||
# """`max` may not be set below `base`"""
|
||||
# self.trait.max = -1
|
||||
# self.check_trait(0, 0, 0, 0, -3, 0)
|
||||
#
|
||||
# def test_no_base_above_max(self):
|
||||
# """`base` may not be set above `max`"""
|
||||
# self.trait.base = 5
|
||||
# self.check_trait(3, 0, 3, 3, -3, 3)
|
||||
#
|
||||
# def test_no_min_above_base(self):
|
||||
# """`min` may not be set above `base`"""
|
||||
# self.trait.min = 1
|
||||
# self.check_trait(0, 0, 0, 0, 0, 3)
|
||||
#
|
||||
# def test_no_base_below_min(self):
|
||||
# """`base` may not be set below `min`"""
|
||||
# self.trait.base = -5
|
||||
# self.check_trait(-3, 0, -3, -3, -3, 3)
|
||||
#
|
||||
# def test_reset_counter(self):
|
||||
# """`reset_to_base()` method sets `current` = `base`"""
|
||||
# self.trait.current = 2
|
||||
# self.check_trait(0, 0, 2, 2, -3, 3)
|
||||
# self.trait.reset_counter()
|
||||
# self.check_trait(0, 0, 0, 0, -3, 3)
|
||||
#
|
||||
# def test_percent_divzero(self):
|
||||
# """confirm `percent()`functionality when unbounded and `base`=0"""
|
||||
# self.trait.min = self.trait.max = None
|
||||
# self.check_trait(0, 0, 0, 0, None, None)
|
||||
# self.assertEqual(self.trait.percent(), '100.0%')
|
||||
# self.trait.current = 20
|
||||
# self.check_trait(0, 0, 20, 20, None, None)
|
||||
# self.assertEqual(self.trait.percent(), '100.0%')
|
||||
#
|
||||
#
|
||||
# class GaugeTraitTestCase(TestCase):
|
||||
# """Test case for `GaugeTrait` functionality"""
|
||||
# def setUp(self):
|
||||
# # direct instantiation for testing only; use TraitHandler in production
|
||||
# self.trait = Trait({
|
||||
# 'name': 'HP',
|
||||
# 'type': 'gauge',
|
||||
# 'base': 10,
|
||||
# 'mod': 0,
|
||||
# 'min': 0,
|
||||
# 'max': 'base'
|
||||
# })
|
||||
#
|
||||
# def tearDown(self):
|
||||
# self.trait = None
|
||||
#
|
||||
# def check_trait(self, base=None, mod=None, current=None,
|
||||
# actual=None, min=None, max=None,):
|
||||
# """helper; allows one-line checking of Trait properties"""
|
||||
# if base is not None: self.assertEqual(self.trait.base, base)
|
||||
# if mod is not None: self.assertEqual(self.trait.mod, mod)
|
||||
# if current is not None: self.assertEqual(self.trait.current, current)
|
||||
# if actual is not None: self.assertEqual(self.trait.actual, actual)
|
||||
# if min is not None: self.assertEqual(self.trait.min, min)
|
||||
# if max is not None: self.assertEqual(self.trait.max, max)
|
||||
#
|
||||
# def test_initial_state(self):
|
||||
# """fixture object properties are as expected"""
|
||||
# self.assertEqual(self.trait.name, 'HP')
|
||||
# self.check_trait(10, 0, 10, 10, 0, 10)
|
||||
#
|
||||
# def test_change_base(self):
|
||||
# """test that changing base property is not constrained when `max`='base'"""
|
||||
# self.trait.base = 20
|
||||
# self.check_trait(20, 0, 20, 20, 0, 20)
|
||||
#
|
||||
# def test_buff_full(self):
|
||||
# """increasing `mod` increases `current`"""
|
||||
# self.trait.mod = 2
|
||||
# self.check_trait(10, 2, 12, 12, 0, 12)
|
||||
# self.trait.reset_mod()
|
||||
# self.check_trait(10, 0, 10, 10, 0, 10)
|
||||
# self.trait.current = 5
|
||||
# self.trait.mod = 2
|
||||
# self.check_trait(10, 2, 7, 7, 0, 12)
|
||||
#
|
||||
# def test_debuff_full(self):
|
||||
# """decreasing `mod` decreases `current` if it would be above `max`"""
|
||||
# self.trait.mod = -2
|
||||
# self.check_trait(10, -2, 8, 8, 0, 8)
|
||||
# self.trait.reset_mod()
|
||||
# self.trait.current = 5
|
||||
# self.trait.mod = -2
|
||||
# self.check_trait(10, -2, 5, 5, 0, 8)
|
||||
#
|
||||
# def test_fill_max_base(self):
|
||||
# """`overfill()` method functionality with default `max`=`base` config"""
|
||||
# self.trait.current = 5
|
||||
# self.check_trait(10, 0, 5, 5, 0, 10)
|
||||
# self.trait.fill_gauge()
|
||||
# self.check_trait(10, 0, 10, 10, 0, 10)
|
||||
#
|
||||
# def test_fill_max_static(self):
|
||||
# """`overfill()` method functionality with static number `max` config"""
|
||||
# self.trait.max = 20
|
||||
# self.trait.current = 5
|
||||
# self.check_trait(10, 0, 5, 5, 0, 20)
|
||||
# self.trait.fill_gauge()
|
||||
# self.check_trait(10, 0, 15, 15, 0, 20) # can exceed `mod`+`base`
|
||||
# self.trait.fill_gauge()
|
||||
# self.check_trait(10, 0, 20, 20, 0, 20) # but not `max`
|
||||
#
|
||||
# def test_fill_max_unbounded(self):
|
||||
# """`overfill()` method functionality with unbounded `max` config"""
|
||||
# self.trait.max = None
|
||||
# self.trait.current = 5
|
||||
# self.trait.mod = 2
|
||||
# self.check_trait(10, 2, 7, 7, 0, None)
|
||||
# self.trait.fill_gauge()
|
||||
# self.check_trait(10, 2, 19, 19, 0, None)
|
||||
#
|
||||
# def test_percent_base(self):
|
||||
# """`percent()` method functionality with `max`=`base`"""
|
||||
# self.trait.base = 100
|
||||
# self.trait.current = 69
|
||||
# self.check_trait(100, 0, 69, 69, 0, 100)
|
||||
# self.assertEqual(self.trait.percent(), '69.0%')
|
||||
#
|
||||
# def test_percent_static(self):
|
||||
# """`percent()` method functionality with static number `max` config."""
|
||||
# self.trait.base = 30
|
||||
# self.trait.mod += 3
|
||||
# self.trait.max = 99
|
||||
# self.check_trait(30, 3, 33, 33, 0, 99)
|
||||
# self.assertEqual(self.trait.percent(), '33.3%')
|
||||
#
|
||||
# def test_percent_unbounded(self):
|
||||
# """`percent()` method functionality with unbounded `max` config."""
|
||||
# self.trait.base = 50
|
||||
# self.trait.max = None
|
||||
# self.trait.current = 75
|
||||
# self.check_trait(50, 0, 75, 75, 0, None)
|
||||
# self.assertEqual(self.trait.percent(), '150.0%')
|
||||
#
|
||||
#
|
||||
# class TraitFactoryTestCase(EvenniaTest):
|
||||
# """Test case for the TraitHandler class."""
|
||||
# def setUp(self):
|
||||
# super(TraitFactoryTestCase, self).setUp()
|
||||
# self.traits = TraitHandler(self.char1)
|
||||
#
|
||||
# def test_add_get(self):
|
||||
# """test adding and getting Traits via TraitHandler"""
|
||||
# self.traits.add(
|
||||
# key='str', name='Strength', type='static')
|
||||
#
|
||||
# t = self.traits.get('str')
|
||||
# self.assertIsInstance(t, Trait)
|
||||
# self.assertEqual(t.name, "Strength")
|
||||
# self.assertEqual(t._type, "static")
|
||||
#
|
||||
# def test_len_remove(self):
|
||||
# """test response to len() and removing Traits from TraitHandler"""
|
||||
# self.traits.add(
|
||||
# key='str', name='Strength', type='static')
|
||||
#
|
||||
# self.assertEqual(len(self.traits), 1)
|
||||
# self.traits.remove('str')
|
||||
# self.assertEqual(len(self.traits), 0)
|
||||
#
|
||||
# def test_all_clear(self):
|
||||
# """test `all` property and clear function on TraitHandler"""
|
||||
# self.traits.add(
|
||||
# key='str', name='Strength', type='static')
|
||||
# self.traits.add(
|
||||
# key='bonus', name='Bonus', type='counter')
|
||||
# self.traits.add(
|
||||
# key='hp', name='HP', type='gauge')
|
||||
#
|
||||
# self.assertEqual(frozenset(self.traits.all),
|
||||
# frozenset(['str', 'bonus', 'hp']))
|
||||
# self.assertEqual(len(self.traits), 3)
|
||||
# self.traits.clear()
|
||||
# self.assertEqual(len(self.traits), 0)
|
||||
#
|
||||
# def test_alternate_access(self):
|
||||
# """test `Trait` access by attribute and dict item syntax"""
|
||||
# self.traits.add(
|
||||
# key='str', name='Strength', type='static')
|
||||
#
|
||||
# # as attribute
|
||||
# self.assertIsInstance(self.traits.str, Trait)
|
||||
# self.assertEqual(self.traits.str.name, 'Strength')
|
||||
# # as dict key
|
||||
# self.assertIsInstance(self.traits['str'], Trait)
|
||||
# self.assertEqual(self.traits['str'].name, 'Strength')
|
||||
#
|
||||
# def test_assignment_error(self):
|
||||
# """ensure attempting to assign to a Trait key on a TraitHandler fails."""
|
||||
# with self.assertRaises(TraitException):
|
||||
# self.traits.str = 5
|
||||
# with self.assertRaises(TraitException):
|
||||
# self.traits['str'] = 5
|
||||
#
|
||||
# def test_defaults_static(self):
|
||||
# """check defaults for static trait optional parameters in config"""
|
||||
# self.traits.add(
|
||||
# key='str', name='Strength', type='static')
|
||||
#
|
||||
# st = self.traits.str
|
||||
# self.assertEqual(st._type, 'static')
|
||||
# self.assertEqual(st.base, 0)
|
||||
# self.assertEqual(st.mod, 0)
|
||||
# self.assertEqual(st.current, 0)
|
||||
# self.assertEqual(st.actual, 0)
|
||||
# with self.assertRaises(AttributeError):
|
||||
# x = st.min
|
||||
# with self.assertRaises(AttributeError):
|
||||
# x = st.max
|
||||
#
|
||||
# def test_defaults_counter(self):
|
||||
# """check defaults for counter trait optional parameters in config"""
|
||||
# self.traits.add(
|
||||
# key='bonus', name='Bonus', type='counter')
|
||||
#
|
||||
# bo = self.traits.bonus
|
||||
# self.assertEqual(bo._type, 'counter')
|
||||
# self.assertEqual(bo.base, 0)
|
||||
# self.assertEqual(bo.mod, 0)
|
||||
# self.assertIs(bo.min, None)
|
||||
# self.assertIs(bo.max, None)
|
||||
# self.assertEqual(bo.extra, [])
|
||||
#
|
||||
# def test_defaults_gauge(self):
|
||||
# """check defaults for gauge trait optional parameters in config"""
|
||||
# self.traits.add(
|
||||
# key='hp', name='HP', type='gauge')
|
||||
#
|
||||
# hp = self.traits.hp
|
||||
# self.assertEqual(hp._type, 'gauge')
|
||||
# self.assertEqual(hp.name, 'HP')
|
||||
# self.assertEqual(hp.base, 0)
|
||||
# self.assertEqual(hp.mod, 0)
|
||||
# self.assertEqual(hp.current, 0)
|
||||
# self.assertEqual(hp.min, 0)
|
||||
# self.assertEqual(hp.max, 0)
|
||||
# self.assertEqual(hp.extra, [])
|
||||
#
|
||||
|
|
|
|||
|
|
@ -257,6 +257,7 @@ Examples:
|
|||
```
|
||||
"""
|
||||
|
||||
from time import time
|
||||
from django.conf import settings
|
||||
from functools import total_ordering
|
||||
from evennia.utils.dbserialize import _SaverDict
|
||||
|
|
@ -945,7 +946,11 @@ class CounterTrait(NumericTrait):
|
|||
5: "traited",
|
||||
7: "expert",
|
||||
9: "master"}
|
||||
|
||||
- rate/ratetarget are optional settings to include a rate-of-change
|
||||
of the current value. This is calculated on-demand and allows for
|
||||
describing a value that is gradually growing smaller/bigger. The
|
||||
increase will stop when either reaching a boundary (if set) or
|
||||
ratetarget. Setting the rate to 0 (default) stops any change.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -958,6 +963,8 @@ class CounterTrait(NumericTrait):
|
|||
"min": None,
|
||||
"max": None,
|
||||
"descs": None,
|
||||
"rate": 0,
|
||||
"ratetarget": None
|
||||
}
|
||||
|
||||
@classmethod
|
||||
|
|
@ -969,17 +976,45 @@ class CounterTrait(NumericTrait):
|
|||
if any(not (isinstance(key, (int, float)) and isinstance(value, str))
|
||||
for key in descs.items()):
|
||||
raise TraitException("Trait descs must be defined on the form {number:str}")
|
||||
if trait_data['rate'] != 0:
|
||||
trait_data['last_update'] = time()
|
||||
return trait_data
|
||||
|
||||
# Helpers
|
||||
# timer component
|
||||
|
||||
def _timer_running(self):
|
||||
"""Check if timer mechanism is running"""
|
||||
return self.rate != 0 and self._data['last_update'] is not None
|
||||
|
||||
def _stop_timer(self):
|
||||
if self._timer_running():
|
||||
self._data['last_update'] = None
|
||||
|
||||
def _check_ratetarget(self):
|
||||
"""Check if we passed ratetarget."""
|
||||
ratetarget = self._data['ratetarget']
|
||||
return (ratetarget is not None and
|
||||
((self.rate < 0 and new_curr <= ratetarget) or
|
||||
(self.rate > 0 and new_curr >= ratetarget)))
|
||||
|
||||
def _update_current(self, current):
|
||||
"""Update current value, including any rate change"""
|
||||
if self.rate != 0 and self._data['last_update'] is not None:
|
||||
tdiff = now - self._data['last_update']
|
||||
current += self.rate * tdiff
|
||||
return current
|
||||
|
||||
def _enforce_boundaries(self, value):
|
||||
"""Ensures that incoming value falls within trait's range."""
|
||||
if self.min is not None and value <= self.min:
|
||||
self._stop_timer()
|
||||
return self.min
|
||||
if self._data["max"] == "base" and value >= self.mod + self.base:
|
||||
return self.base + self.mod
|
||||
if self.max is not None and value >= self.max:
|
||||
self._stop_timer()
|
||||
return self.max
|
||||
if self._timer_running() and self._check_ratetarget():
|
||||
_stop_timer()
|
||||
return self._data['ratetarget']
|
||||
return value
|
||||
|
||||
# properties
|
||||
|
|
@ -1046,7 +1081,7 @@ class CounterTrait(NumericTrait):
|
|||
@property
|
||||
def current(self):
|
||||
"""The `current` value of the `Trait`. This does not have .mod added."""
|
||||
return self._data.get("current", self.base)
|
||||
return self._update_current(self._data.get("current", self.base))
|
||||
|
||||
@current.setter
|
||||
def current(self, value):
|
||||
|
|
@ -1148,7 +1183,9 @@ class GaugeTrait(CounterTrait):
|
|||
"base": 0,
|
||||
"mod": 0,
|
||||
"min": 0,
|
||||
"descs": None
|
||||
"descs": None,
|
||||
"rate": 0,
|
||||
"ratetarget": None,
|
||||
}
|
||||
|
||||
def _enforce_boundaries(self, value):
|
||||
|
|
@ -1215,8 +1252,8 @@ class GaugeTrait(CounterTrait):
|
|||
@property
|
||||
def current(self):
|
||||
"""The `current` value of the gauge."""
|
||||
return self._enforce_boundaries(
|
||||
self._data.get("current", self.base + self.mod))
|
||||
return self._update_current(self._enforce_boundaries(
|
||||
self._data.get("current", self.base + self.mod)))
|
||||
|
||||
@current.setter
|
||||
def current(self, value):
|
||||
|
|
@ -1255,15 +1292,7 @@ class GaugeTrait(CounterTrait):
|
|||
del self.current
|
||||
|
||||
|
||||
class SequenceTrait(CounterTrait):
|
||||
class UpdatingTrait(CounterTrait):
|
||||
"""
|
||||
A trait that stores an indexed array of strings to
|
||||
represent distinct values in a sequence. Adding to the trait will
|
||||
step back and forth in the sequence.
|
||||
|
||||
This is useful for systems which don't use numbers as much
|
||||
as discrete states to represent things, such as
|
||||
|
||||
"Weak, "
|
||||
|
||||
This is a trait that
|
||||
"""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue