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

Feature to 'damage' life bar when 'Again' is selected #35

Merged
merged 2 commits into from
Jun 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ Filtered deck configurations (Added in 2018-07-01):

- **Maximum life**: Is the time in seconds for the life bar go from full to empty.
- **Recover**: Is the time in seconds that is recovered after answering a card.
- **Enable damage**: Select this to reduce the time remaining on the life bar each time a card is responded to with 'Again'.
- **Damage**: Is the time in seconds that is removed when a card is responded to with 'Again'.
- **Current life**: Your current life, in case you want to set it for whatever reason.

### Pause drain during reviews
Expand All @@ -61,15 +63,17 @@ Whenever the life drops to 0, the hook `LifeDrain.gameOver` is triggered.
You may use it in your add-on to make something interesting happen.

And there is a method you can call using hook to recover (or drain) the user's life.
It has 2 optional parameters:
It has 3 optional parameters:
1st is `increment` (boolean), True to recover (default) and False to drain.
2nd is `value` (integer). Default is the recover value set by the user in the deck preferences.
3rd is `damage` (boolean). If set to true and no `value` is supplied, the damage value set by the user in the deck preferences is subtracted. The value of `increment` is ignored when this parameter is in use.

Examples:

- `runHook('LifeDrain.recover')` recovers the life using the default value in deck preferences
- `runHook('LifeDrain.recover', False)` drains the life using the default value in deck preferences
- `runHook('LifeDrain.recover', True, 9999)` recovers all the life
- `runHook('LifeDrain.recover', True, None, True)` drains the life using the damage value in deck preferences

## Inspiration
This add-on was inspired on the add-on [Progress Bar](https://ankiweb.net/shared/info/2091361802) and the game [osu!](https://osu.ppy.sh/).
Expand All @@ -81,6 +85,7 @@ The [Progress Bar](https://ankiweb.net/shared/info/2091361802) add-on showed me
And then I just thought: why not to have a life bar with drain in Anki?

## CHANGELOG
- **2019-05-26**: Add 'damage' feature.
- **2019-04-28**: Fix bug when selecting bar colors on Mac OS. ([Issue #30](https://github.com/Yutsuten/anki-lifedrain/issues/30))
- **2019-01-12**: Added option to stop drain on answer shown.
- **2018-12-09**: Added disable option and some hooks to allow integration with other add-ons.
Expand Down
57 changes: 49 additions & 8 deletions src/lifedrain/lifedrain.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
(c) SebastienGllmt 2017 <https://github.com/SebastienGllmt/>
(c) Glutanimate 2017 <https://glutanimate.com/>
(c) Yutsuten 2018 <https://github.com/Yutsuten>
(c) Al Beano 2019 <https://github.com/whiteisthenewblack>
License: GNU AGPLv3 or later <https://www.gnu.org/licenses/agpl.html>
'''

Expand Down Expand Up @@ -47,6 +48,8 @@
DEFAULTS = {
'maxLife': 120,
'recover': 5,
'enableDamage': False,
'damage': 5,
'barPosition': POSITION_OPTIONS.index('Bottom'),
'barHeight': 15,
'barBgColor': '#f3f3f2',
Expand Down Expand Up @@ -75,7 +78,8 @@ class LifeDrain(object): # pylint: disable=too-few-public-methods
status = {
'reviewed': False,
'newCardState': False,
'screen': None
'screen': None,
'reviewResponse': 0
}
stopOnAnswer = False
disable = None
Expand Down Expand Up @@ -363,13 +367,18 @@ def deckSettingsLifeDrainTabUi(self, Dialog):
self, row,
'The <b>maximum life</b> is the time in seconds for the life bar go '
'from full to empty.\n<b>Recover</b> is the time in seconds that is '
'recovered after answering a card.'
'recovered after answering a card. <b>Damage</b> is the life lost '
'when a card is answered with \'Again\'.'
)
row += 1
createSpinBox(self, row, 'maxLifeInput', 'Maximum life', [1, 10000])
row += 1
createSpinBox(self, row, 'recoverInput', 'Recover', [0, 1000])
row += 1
createCheckBox(self, row, 'enableDamageInput', 'Enable damage')
row += 1
createSpinBox(self, row, 'damageInput', 'Damage', [-1000, 1000])
row += 1
createSpinBox(self, row, 'currentValueInput', 'Current life', [0, 10000])
row += 1
fillRemainingSpace(self, row)
Expand All @@ -389,6 +398,12 @@ def loadDeckConf(self):
self.form.recoverInput.setValue(
self.conf.get('recover', DEFAULTS['recover'])
)
self.form.enableDamageInput.setChecked(
self.conf.get('enableDamage', DEFAULTS['enableDamage'])
)
self.form.damageInput.setValue(
self.conf.get('damage', DEFAULTS['damage'])
)
self.form.currentValueInput.setValue(
lifeDrain.deckBarManager.getDeckConf(self.deck['id'])['currentValue']
)
Expand All @@ -403,6 +418,8 @@ def saveDeckConf(self):
self.conf['maxLife'] = self.form.maxLifeInput.value()
self.conf['recover'] = self.form.recoverInput.value()
self.conf['currentValue'] = self.form.currentValueInput.value()
self.conf['enableDamage'] = self.form.enableDamageInput.isChecked()
self.conf['damage'] = self.form.damageInput.value()
lifeDrain.deckBarManager.setDeckConf(self.deck['id'], self.conf)


Expand All @@ -417,6 +434,10 @@ def customStudyLifeDrainUi(self, Dialog):
row += 1
createSpinBox(self, row, 'recoverInput', 'Recover', [0, 1000])
row += 1
createCheckBox(self, row, 'enableDamageInput', 'Enable damage')
row += 1
createSpinBox(self, row, 'damageInput', 'Damage', [-1000, 1000])
row += 1
createSpinBox(self, row, 'currentValueInput', 'Current life', [0, 10000])
row += 1
index = 2 if appVersion.startswith('2.0') else 3
Expand Down Expand Up @@ -658,7 +679,9 @@ def addDeck(self, deckId, conf):
self._barInfo[str(deckId)] = {
'maxValue': conf.get('maxLife', DEFAULTS['maxLife']),
'currentValue': conf.get('maxLife', DEFAULTS['maxLife']),
'recoverValue': conf.get('recover', DEFAULTS['recover'])
'recoverValue': conf.get('recover', DEFAULTS['recover']),
'enableDamageValue': conf.get('enableDamage', DEFAULTS['enableDamage']),
'damageValue': conf.get('damage', DEFAULTS['damage'])
}

def setDeck(self, deckId):
Expand Down Expand Up @@ -688,12 +711,16 @@ def setDeckConf(self, deckId, conf):
'''
maxLife = conf.get('maxLife', DEFAULTS['maxLife'])
recover = conf.get('recover', DEFAULTS['recover'])
enableDamage = conf.get('enableDamage', DEFAULTS['enableDamage'])
damage = conf.get('damage', DEFAULTS['damage'])
currentValue = conf.get('currentValue', DEFAULTS['maxLife'])
if currentValue > maxLife:
currentValue = maxLife

self._barInfo[str(deckId)]['maxValue'] = maxLife
self._barInfo[str(deckId)]['recoverValue'] = recover
self._barInfo[str(deckId)]['enableDamageValue'] = enableDamage
self._barInfo[str(deckId)]['damageValue'] = damage
self._barInfo[str(deckId)]['currentValue'] = currentValue

def setAnkiProgressBarStyle(self, config=None):
Expand Down Expand Up @@ -723,15 +750,19 @@ def setAnkiProgressBarStyle(self, config=None):
if self._currentDeck is not None:
self.recover(value=0)

def recover(self, increment=True, value=None):
def recover(self, increment=True, value=None, damage=False):
'''
Abstraction for recovering life, increments the bar if increment is True (default).
'''
multiplier = 1
if not increment:
multiplier = -1
if value is None:
value = self._barInfo[self._currentDeck]['recoverValue']
if damage and self._barInfo[self._currentDeck]['enableDamageValue']:
multiplier = -1
value = self._barInfo[self._currentDeck]['damageValue']
else:
value = self._barInfo[self._currentDeck]['recoverValue']

self._ankiProgressBar.incCurrentValue(multiplier * value)

Expand Down Expand Up @@ -822,7 +853,10 @@ def showQuestion():
if not lifeDrain.disable:
activateTimer()
if lifeDrain.status['reviewed']:
lifeDrain.deckBarManager.recover()
if lifeDrain.status['reviewResponse'] == 1:
lifeDrain.deckBarManager.recover(damage=True)
else:
lifeDrain.deckBarManager.recover()
lifeDrain.status['reviewed'] = False
lifeDrain.status['newCardState'] = False

Expand Down Expand Up @@ -916,13 +950,19 @@ def toggleTimer():
lifeDrain.timer.start()


def recover(increment=True, value=None):
def recover(increment=True, value=None, damage=False):
'''
Method ran when invoking 'LifeDrain.recover' hook.
'''
lifeDrain = getLifeDrain()
lifeDrain.deckBarManager.recover(increment, value)
lifeDrain.deckBarManager.recover(increment, value, damage)

def answerCard(self, resp):
'''
Called when a card is answered
'''
lifeDrain = getLifeDrain()
lifeDrain.status['reviewResponse'] = resp

# Dealing with key presses is different in Anki 2.0 and 2.1
# This if/elif block deals with the differences
Expand Down Expand Up @@ -961,3 +1001,4 @@ def _addShortcut(shortcuts):
Scheduler.suspendCards = wrap(Scheduler.suspendCards, suspend)
_Collection.remCards = wrap(_Collection.remCards, delete)
EditCurrent.__init__ = wrap(EditCurrent.__init__, onEdit)
Reviewer._answerCard = wrap(Reviewer._answerCard, answerCard, "before")