SIG SELECT FYI: mechanisms→energies, articulations→operations; .sig-caution→.sig-info; .btn-caution→.btn-info — TDD
- TarotCard.mechanisms renamed to energies, articulations to operations (migration 0008); energies_json + operations_json properties replace old names - migration 0008 also seeds The Schizo (card 1) w. 4 Energies (LIBIDO/NUMEN/VOLUPTAS×2) + 4 Operations (COVER/CROWN/BEHIND/BEFORE) - FYI info panel renamed throughout: .sig-caution-* → .sig-info-*; data-mechanisms → data-energies; data-articulations → data-operations - _renderCaution() now sets dynamic title (Energies/Operations) + .sig-info-title--energies/ --operations colour modifier; type element shows entry.type (LIBIDO, COVER etc.) - .btn-caution → .btn-info across note.js, role-select.js, specs, FT + _button-pad.scss rule - Major arcana reversed face: card title always shown (reversal concept moves to FYI) - SigSelectSpec.js rewritten: 242 specs; FYI describe block updated for energies/operations Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -21,7 +21,7 @@ const Note = (() => {
|
||||
'</div>' +
|
||||
'<div class="note-banner__image"></div>' +
|
||||
'<button type="button" class="btn btn-cancel note-banner__nvm">NVM</button>' +
|
||||
'<a href="/billboard/my-notes/" class="btn btn-caution note-banner__fyi">FYI</a>';
|
||||
'<a href="/billboard/my-notes/" class="btn btn-info note-banner__fyi">FYI</a>';
|
||||
|
||||
banner.querySelector('.note-banner__nvm').addEventListener('click', function () {
|
||||
banner.remove();
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
"""Rename mechanisms→energies and articulations→operations on TarotCard;
|
||||
seed The Schizo (Earthman major arcana card 1) with Energy and Operation entries.
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
SCHIZO_ENERGIES = [
|
||||
{"type": "LIBIDO", "effect": "When encountering territorial Libido, may convert Emanation into 1. The Priest."},
|
||||
{"type": "NUMEN", "effect": "When encountering despotic Numen, may convert Emanation into 1. The Powerful."},
|
||||
{"type": "VOLUPTAS", "effect": "When encountering axiomatic Voluptas, may convert Emanation into 1. The Normal."},
|
||||
{"type": "VOLUPTAS", "effect": "When encountering annihilating Voluptas, may convert Emanation into 1. The Surrendered."},
|
||||
]
|
||||
|
||||
SCHIZO_OPERATIONS = [
|
||||
{"type": "COVER", "effect": "When covering 2. The Occultist she may choose, by converting her own Reversal into 2. Pestilence, to convert this Reversal into 1. The Pervert."},
|
||||
{"type": "CROWN", "effect": "When crowning 3. The Despot she may choose, by converting her own Reversal into 3. War, to convert this Reversal into 1. The Paranoiac."},
|
||||
{"type": "BEHIND", "effect": "When behind 4. The Capitalist he may choose, by converting his own Reversal into 4. Famine, to convert this Reversal into 1. The Neurotic."},
|
||||
{"type": "BEFORE", "effect": "When before 5. The Fascist he may choose, by converting his own Reversal into 5. Death, to convert this Reversal into 1. The Suicidal."},
|
||||
]
|
||||
|
||||
|
||||
def seed_schizo(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
try:
|
||||
earthman = DeckVariant.objects.get(slug="earthman")
|
||||
except DeckVariant.DoesNotExist:
|
||||
return
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR", number=1,
|
||||
).update(energies=SCHIZO_ENERGIES, operations=SCHIZO_OPERATIONS)
|
||||
|
||||
|
||||
def clear_schizo(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
try:
|
||||
earthman = DeckVariant.objects.get(slug="earthman")
|
||||
except DeckVariant.DoesNotExist:
|
||||
return
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR", number=1,
|
||||
).update(energies=[], operations=[])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0007_populate_middle_arcana_reversals"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField("TarotCard", "mechanisms", "energies"),
|
||||
migrations.RenameField("TarotCard", "articulations", "operations"),
|
||||
migrations.RunPython(seed_schizo, reverse_code=clear_schizo),
|
||||
]
|
||||
@@ -257,8 +257,8 @@ class TarotCard(models.Model):
|
||||
gravity_emanation = models.CharField(max_length=200, blank=True, default='')
|
||||
levity_reversal = models.CharField(max_length=200, blank=True, default='') # polarity-split reversal (card 48)
|
||||
gravity_reversal = models.CharField(max_length=200, blank=True, default='')
|
||||
mechanisms = models.JSONField(default=list) # list of dicts; in-game effects
|
||||
articulations = models.JSONField(default=list) # list of dicts; combinatory effects
|
||||
energies = models.JSONField(default=list) # list of {type, effect} dicts — Energy interactions
|
||||
operations = models.JSONField(default=list) # list of {type, effect} dicts — Operation interactions
|
||||
keywords_upright = models.JSONField(default=list)
|
||||
keywords_reversed = models.JSONField(default=list)
|
||||
cautions = models.JSONField(default=list)
|
||||
@@ -342,14 +342,14 @@ class TarotCard(models.Model):
|
||||
return json.dumps(self.cautions)
|
||||
|
||||
@property
|
||||
def mechanisms_json(self):
|
||||
def energies_json(self):
|
||||
import json
|
||||
return json.dumps(self.mechanisms)
|
||||
return json.dumps(self.energies)
|
||||
|
||||
@property
|
||||
def articulations_json(self):
|
||||
def operations_json(self):
|
||||
import json
|
||||
return json.dumps(self.articulations)
|
||||
return json.dumps(self.operations)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@@ -48,7 +48,7 @@ var RoleSelect = (function () {
|
||||
el.innerHTML =
|
||||
"<p>Equip card deck before Role select</p>" +
|
||||
"<div class=\"guard-actions\">" +
|
||||
"<a class=\"btn btn-caution\" href=\"/gameboard/\">FYI</a>" +
|
||||
"<a class=\"btn btn-info\" href=\"/gameboard/\">FYI</a>" +
|
||||
"<button class=\"btn btn-cancel\">NVM</button>" +
|
||||
"</div>";
|
||||
el.querySelector(".btn-cancel").addEventListener("click", function () {
|
||||
|
||||
@@ -6,7 +6,7 @@ var SigSelect = (function () {
|
||||
};
|
||||
|
||||
var overlay, deckGrid, stage, stageCard, statBlock;
|
||||
var cautionEl, cautionEffect, cautionTitle, cautionPrev, cautionNext, cautionIndexEl;
|
||||
var cautionEl, cautionEffect, cautionTitle, cautionTypeEl, cautionPrev, cautionNext, cautionIndexEl;
|
||||
var _flipBtn, _cautionBtn, _flipOrigLabel, _cautionOrigLabel;
|
||||
var reserveUrl, readyUrl, userRole, userPolarity;
|
||||
|
||||
@@ -47,15 +47,20 @@ var SigSelect = (function () {
|
||||
|
||||
function _renderCaution() {
|
||||
if (_cautionData.length === 0) {
|
||||
if (cautionTitle) cautionTitle.textContent = 'Ally Interaction';
|
||||
cautionEffect.innerHTML = '<em>No ally interactions defined.</em>';
|
||||
cautionTitle.textContent = 'Energies';
|
||||
cautionTitle.className = 'sig-info-title sig-info-title--energies';
|
||||
if (cautionTypeEl) cautionTypeEl.textContent = '';
|
||||
cautionEffect.innerHTML = '<em>No interactions defined.</em>';
|
||||
cautionPrev.disabled = true;
|
||||
cautionNext.disabled = true;
|
||||
cautionIndexEl.textContent = '';
|
||||
return;
|
||||
}
|
||||
var entry = _cautionData[_cautionIdx];
|
||||
if (cautionTitle) cautionTitle.textContent = entry.category || '';
|
||||
var isEnergies = entry.category === 'energies';
|
||||
cautionTitle.textContent = isEnergies ? 'Energies' : 'Operations';
|
||||
cautionTitle.className = 'sig-info-title sig-info-title--' + entry.category;
|
||||
if (cautionTypeEl) cautionTypeEl.textContent = entry.type || '';
|
||||
cautionEffect.innerHTML = entry.effect || '';
|
||||
cautionPrev.disabled = (_cautionData.length <= 1);
|
||||
cautionNext.disabled = (_cautionData.length <= 1);
|
||||
@@ -67,9 +72,13 @@ var SigSelect = (function () {
|
||||
function _openCaution() {
|
||||
if (!_focusedCardEl) return;
|
||||
try {
|
||||
var mechanisms = JSON.parse(_focusedCardEl.dataset.mechanisms || '[]');
|
||||
var articulations = JSON.parse(_focusedCardEl.dataset.articulations || '[]');
|
||||
_cautionData = mechanisms.concat(articulations);
|
||||
var energies = JSON.parse(_focusedCardEl.dataset.energies || '[]');
|
||||
var operations = JSON.parse(_focusedCardEl.dataset.operations || '[]');
|
||||
_cautionData = energies.map(function (e) {
|
||||
return { type: e.type, effect: e.effect, category: 'energies' };
|
||||
}).concat(operations.map(function (o) {
|
||||
return { type: o.type, effect: o.effect, category: 'operations' };
|
||||
}));
|
||||
} catch (e) {
|
||||
_cautionData = [];
|
||||
}
|
||||
@@ -79,11 +88,11 @@ var SigSelect = (function () {
|
||||
_cautionBtn.classList.add('btn-disabled');
|
||||
_flipBtn.textContent = '\u00D7';
|
||||
_cautionBtn.textContent = '\u00D7';
|
||||
stage.classList.add('sig-caution-open');
|
||||
stage.classList.add('sig-info-open');
|
||||
}
|
||||
|
||||
function _closeCaution() {
|
||||
stage.classList.remove('sig-caution-open');
|
||||
stage.classList.remove('sig-info-open');
|
||||
if (_flipBtn) {
|
||||
_flipBtn.classList.remove('btn-disabled');
|
||||
_cautionBtn.classList.remove('btn-disabled');
|
||||
@@ -140,7 +149,7 @@ var SigSelect = (function () {
|
||||
var reversal = cardEl.dataset.reversal || '';
|
||||
if (isMajor) {
|
||||
stageCard.querySelector('.fan-card-reversal-qualifier').textContent = qualifier;
|
||||
stageCard.querySelector('.fan-card-reversal-name').textContent = reversal;
|
||||
stageCard.querySelector('.fan-card-reversal-name').textContent = title;
|
||||
} else if (reversal) {
|
||||
stageCard.querySelector('.fan-card-reversal-qualifier').textContent = reversal;
|
||||
stageCard.querySelector('.fan-card-reversal-name').textContent = title;
|
||||
@@ -629,7 +638,7 @@ var SigSelect = (function () {
|
||||
statBlock = stage.querySelector('.sig-stat-block');
|
||||
|
||||
_flipBtn = statBlock.querySelector('.sig-flip-btn');
|
||||
_cautionBtn = statBlock.querySelector('.sig-caution-btn');
|
||||
_cautionBtn = statBlock.querySelector('.sig-info-btn');
|
||||
_flipOrigLabel = _flipBtn.textContent;
|
||||
_cautionOrigLabel = _cautionBtn.textContent;
|
||||
|
||||
@@ -639,12 +648,13 @@ var SigSelect = (function () {
|
||||
stageCard.classList.toggle('stage-card--reversed');
|
||||
});
|
||||
|
||||
cautionEl = stage.querySelector('.sig-caution-tooltip');
|
||||
cautionEffect = cautionEl.querySelector('.sig-caution-effect');
|
||||
cautionTitle = cautionEl.querySelector('.sig-caution-title');
|
||||
cautionPrev = statBlock.querySelector('.sig-caution-prev');
|
||||
cautionNext = statBlock.querySelector('.sig-caution-next');
|
||||
cautionIndexEl = cautionEl.querySelector('.sig-caution-index');
|
||||
cautionEl = stage.querySelector('.sig-info');
|
||||
cautionEffect = cautionEl.querySelector('.sig-info-effect');
|
||||
cautionTitle = cautionEl.querySelector('.sig-info-title');
|
||||
cautionTypeEl = cautionEl.querySelector('.sig-info-type');
|
||||
cautionPrev = statBlock.querySelector('.sig-info-prev');
|
||||
cautionNext = statBlock.querySelector('.sig-info-next');
|
||||
cautionIndexEl = cautionEl.querySelector('.sig-info-index');
|
||||
|
||||
// Clicking the tooltip (not nav buttons) dismisses it
|
||||
cautionEl.addEventListener('click', function () {
|
||||
@@ -653,7 +663,7 @@ var SigSelect = (function () {
|
||||
|
||||
_cautionBtn.addEventListener('click', function () {
|
||||
if (_cautionBtn.classList.contains('btn-disabled')) return;
|
||||
stage.classList.contains('sig-caution-open') ? _closeCaution() : _openCaution();
|
||||
stage.classList.contains('sig-info-open') ? _closeCaution() : _openCaution();
|
||||
});
|
||||
cautionPrev.addEventListener('click', function () {
|
||||
_cautionIdx = (_cautionIdx - 1 + _cautionData.length) % _cautionData.length;
|
||||
|
||||
Reference in New Issue
Block a user