collapse migrations: 41 epic + 20 lyric + 12 applets + others → fresh initials + 4 themed seeds
- Delete all incremental migration files across all apps; regenerate 0001_initial.py per app via makemigrations (schema unchanged, no model edits) - applets/0003_seed_applets.py: all 20 Applet rows in one migration - epic/0003_seed_fiorentine_deck.py: Fiorentine Minchiate DeckVariant + 78 cards - epic/0004_seed_earthman_deck.py: Earthman DeckVariant + 50 major + 56 minor/middle arcana (106 cards); stray PENTACLES courts absent — clean from the start - epic/0005_seed_astro_reference_tables.py: 12 signs, 10 planets, 9 aspect types (incl. Semisquare + Sesquiquadrate), 12 house labels - 706 ITs green on fresh DB 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:
@@ -1,8 +1,7 @@
|
||||
# Generated by Django 6.0 on 2026-03-12 19:46
|
||||
# Generated by Django 6.0 on 2026-04-28 00:59
|
||||
|
||||
import django.db.models.deletion
|
||||
import datetime
|
||||
import uuid
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
@@ -11,22 +10,50 @@ class Migration(migrations.Migration):
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Room',
|
||||
name='AspectType',
|
||||
fields=[
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=200)),
|
||||
('visibility', models.CharField(choices=[('PRIVATE', 'Private'), ('PUBLIC', 'Public'), ('INVITE ONLY', 'Invite Only')], default='PRIVATE', max_length=20)),
|
||||
('gate_status', models.CharField(choices=[('GATHERING', 'Gathering'), ('OPEN', 'Open'), ('RENEWAL_DUE', 'Renewal Due')], default='GATHERING', max_length=20)),
|
||||
('renewal_period', models.DurationField(blank=True, null=True)),
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=20, unique=True)),
|
||||
('symbol', models.CharField(max_length=5)),
|
||||
('angle', models.PositiveSmallIntegerField()),
|
||||
('orb', models.FloatField()),
|
||||
],
|
||||
options={
|
||||
'ordering': ['angle'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Character',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('birth_dt', models.DateTimeField(blank=True, null=True)),
|
||||
('birth_lat', models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True)),
|
||||
('birth_lon', models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True)),
|
||||
('birth_place', models.CharField(blank=True, max_length=200)),
|
||||
('house_system', models.CharField(choices=[('O', 'Porphyry'), ('P', 'Placidus'), ('K', 'Koch'), ('W', 'Whole Sign')], default='O', max_length=1)),
|
||||
('chart_data', models.JSONField(blank=True, null=True)),
|
||||
('celtic_cross', models.JSONField(blank=True, null=True)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('board_state', models.JSONField(default=dict)),
|
||||
('seed_count', models.IntegerField(default=12)),
|
||||
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='owned_rooms', to=settings.AUTH_USER_MODEL)),
|
||||
('confirmed_at', models.DateTimeField(blank=True, null=True)),
|
||||
('retired_at', models.DateTimeField(blank=True, null=True)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['-created_at'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='DeckVariant',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=100, unique=True)),
|
||||
('slug', models.SlugField(unique=True)),
|
||||
('card_count', models.IntegerField()),
|
||||
('description', models.TextField(blank=True)),
|
||||
('is_default', models.BooleanField(default=False)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
@@ -37,9 +64,129 @@ class Migration(migrations.Migration):
|
||||
('status', models.CharField(choices=[('EMPTY', 'Empty'), ('RESERVED', 'Reserved'), ('FILLED', 'Filled')], default='EMPTY', max_length=10)),
|
||||
('reserved_at', models.DateTimeField(blank=True, null=True)),
|
||||
('filled_at', models.DateTimeField(blank=True, null=True)),
|
||||
('funded_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='funded_slots', to=settings.AUTH_USER_MODEL)),
|
||||
('gamer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='gate_slots', to=settings.AUTH_USER_MODEL)),
|
||||
('room', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='gate_slots', to='epic.room')),
|
||||
('debited_token_type', models.CharField(blank=True, max_length=8, null=True)),
|
||||
('debited_token_expires_at', models.DateTimeField(blank=True, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='HouseLabel',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('number', models.PositiveSmallIntegerField(unique=True)),
|
||||
('name', models.CharField(max_length=30)),
|
||||
('keywords', models.CharField(blank=True, max_length=100)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['number'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Planet',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=20, unique=True)),
|
||||
('symbol', models.CharField(max_length=5)),
|
||||
('order', models.PositiveSmallIntegerField(unique=True)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['order'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Room',
|
||||
fields=[
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=200)),
|
||||
('visibility', models.CharField(choices=[('PRIVATE', 'Private'), ('PUBLIC', 'Public'), ('INVITE ONLY', 'Invite Only')], default='PRIVATE', max_length=20)),
|
||||
('gate_status', models.CharField(choices=[('GATHERING', 'GATHERING GAMERS'), ('OPEN', 'Open'), ('RENEWAL_DUE', 'Renewal Due')], default='GATHERING', max_length=20)),
|
||||
('table_status', models.CharField(blank=True, choices=[('ROLE_SELECT', 'Role Select'), ('SIG_SELECT', 'Significator Select'), ('SKY_SELECT', 'Sky Select'), ('IN_GAME', 'In Game')], max_length=20, null=True)),
|
||||
('sig_select_started_at', models.DateTimeField(blank=True, null=True)),
|
||||
('renewal_period', models.DurationField(blank=True, default=datetime.timedelta(days=7), null=True)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('board_state', models.JSONField(default=dict)),
|
||||
('seed_count', models.IntegerField(default=12)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='RoomInvite',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('invitee_email', models.EmailField(max_length=254)),
|
||||
('status', models.CharField(choices=[('PENDING', 'Pending'), ('ACCEPTED', 'Accepted'), ('DECLINED', 'Declined')], default='PENDING', max_length=10)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Sign',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=20, unique=True)),
|
||||
('symbol', models.CharField(max_length=5)),
|
||||
('element', models.CharField(choices=[('Fire', 'Fire'), ('Earth', 'Earth'), ('Air', 'Air'), ('Water', 'Water')], max_length=5)),
|
||||
('modality', models.CharField(choices=[('Cardinal', 'Cardinal'), ('Fixed', 'Fixed'), ('Mutable', 'Mutable')], max_length=8)),
|
||||
('order', models.PositiveSmallIntegerField(unique=True)),
|
||||
('start_degree', models.FloatField()),
|
||||
],
|
||||
options={
|
||||
'ordering': ['order'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SigReservation',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('role', models.CharField(max_length=2)),
|
||||
('polarity', models.CharField(choices=[('levity', 'Levity'), ('gravity', 'Gravity')], max_length=7)),
|
||||
('reserved_at', models.DateTimeField(auto_now_add=True)),
|
||||
('ready', models.BooleanField(default=False)),
|
||||
('countdown_remaining', models.IntegerField(blank=True, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TableSeat',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('slot_number', models.IntegerField()),
|
||||
('role', models.CharField(blank=True, choices=[('PC', 'Player'), ('BC', 'Builder'), ('SC', 'Shepherd'), ('AC', 'Alchemist'), ('NC', 'Narrator'), ('EC', 'Economist')], max_length=2, null=True)),
|
||||
('role_revealed', models.BooleanField(default=False)),
|
||||
('seat_position', models.IntegerField(blank=True, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TarotCard',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=200)),
|
||||
('arcana', models.CharField(choices=[('MAJOR', 'Major Arcana'), ('MINOR', 'Minor Arcana'), ('MIDDLE', 'Middle Arcana')], max_length=6)),
|
||||
('suit', models.CharField(blank=True, choices=[('WANDS', 'Wands'), ('CUPS', 'Cups'), ('SWORDS', 'Swords'), ('PENTACLES', 'Pentacles'), ('CROWNS', 'Crowns'), ('BRANDS', 'Brands'), ('GRAILS', 'Grails'), ('BLADES', 'Blades')], max_length=10, null=True)),
|
||||
('icon', models.CharField(blank=True, default='', max_length=50)),
|
||||
('number', models.IntegerField()),
|
||||
('slug', models.SlugField(max_length=120)),
|
||||
('correspondence', models.CharField(blank=True, max_length=200)),
|
||||
('group', models.CharField(blank=True, max_length=100)),
|
||||
('reversal', models.CharField(blank=True, default='', max_length=200)),
|
||||
('levity_qualifier', models.CharField(blank=True, default='', max_length=100)),
|
||||
('gravity_qualifier', models.CharField(blank=True, default='', max_length=100)),
|
||||
('levity_emanation', models.CharField(blank=True, default='', max_length=200)),
|
||||
('gravity_emanation', models.CharField(blank=True, default='', max_length=200)),
|
||||
('levity_reversal', models.CharField(blank=True, default='', max_length=200)),
|
||||
('gravity_reversal', models.CharField(blank=True, default='', max_length=200)),
|
||||
('mechanisms', models.JSONField(default=list)),
|
||||
('articulations', models.JSONField(default=list)),
|
||||
('keywords_upright', models.JSONField(default=list)),
|
||||
('keywords_reversed', models.JSONField(default=list)),
|
||||
('cautions', models.JSONField(default=list)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['deck_variant', 'arcana', 'suit', 'number'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TarotDeck',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('drawn_card_ids', models.JSONField(default=list)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
# Generated by Django 6.0 on 2026-03-13 20:32
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='room',
|
||||
name='renewal_period',
|
||||
field=models.DurationField(blank=True, default=datetime.timedelta(days=7), null=True),
|
||||
),
|
||||
]
|
||||
120
src/apps/epic/migrations/0002_initial.py
Normal file
120
src/apps/epic/migrations/0002_initial.py
Normal file
@@ -0,0 +1,120 @@
|
||||
# Generated by Django 6.0 on 2026-04-28 00:59
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('epic', '0001_initial'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='gateslot',
|
||||
name='funded_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='funded_slots', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='gateslot',
|
||||
name='gamer',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='gate_slots', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='room',
|
||||
name='owner',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='owned_rooms', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='gateslot',
|
||||
name='room',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='gate_slots', to='epic.room'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='roominvite',
|
||||
name='inviter',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sent_invites', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='roominvite',
|
||||
name='room',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='invites', to='epic.room'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='sigreservation',
|
||||
name='gamer',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sig_reservations', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='sigreservation',
|
||||
name='room',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sig_reservations', to='epic.room'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tableseat',
|
||||
name='gamer',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='table_seats', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tableseat',
|
||||
name='room',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='table_seats', to='epic.room'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='sigreservation',
|
||||
name='seat',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='sig_reservation', to='epic.tableseat'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='character',
|
||||
name='seat',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='characters', to='epic.tableseat'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tarotcard',
|
||||
name='deck_variant',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cards', to='epic.deckvariant'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tableseat',
|
||||
name='significator',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='significator_seats', to='epic.tarotcard'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='sigreservation',
|
||||
name='card',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sig_reservations', to='epic.tarotcard'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='character',
|
||||
name='significator',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='character_significators', to='epic.tarotcard'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tarotdeck',
|
||||
name='deck_variant',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='active_decks', to='epic.deckvariant'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tarotdeck',
|
||||
name='room',
|
||||
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='tarot_deck', to='epic.room'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='tarotcard',
|
||||
unique_together={('deck_variant', 'slug')},
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='sigreservation',
|
||||
constraint=models.UniqueConstraint(fields=('room', 'gamer'), name='one_sig_reservation_per_gamer_per_room'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='sigreservation',
|
||||
constraint=models.UniqueConstraint(fields=('room', 'card', 'polarity'), name='one_reservation_per_card_per_polarity_per_room'),
|
||||
),
|
||||
]
|
||||
@@ -1,27 +0,0 @@
|
||||
# Generated by Django 6.0 on 2026-03-13 22:19
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0002_alter_room_renewal_period'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='RoomInvite',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('invitee_email', models.EmailField(max_length=254)),
|
||||
('status', models.CharField(choices=[('PENDING', 'Pending'), ('ACCEPTED', 'Accepted'), ('DECLINED', 'Declined')], default='PENDING', max_length=10)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('inviter', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sent_invites', to=settings.AUTH_USER_MODEL)),
|
||||
('room', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='invites', to='epic.room')),
|
||||
],
|
||||
),
|
||||
]
|
||||
121
src/apps/epic/migrations/0003_seed_fiorentine_deck.py
Normal file
121
src/apps/epic/migrations/0003_seed_fiorentine_deck.py
Normal file
@@ -0,0 +1,121 @@
|
||||
"""Seed the Fiorentine Minchiate deck (78 cards)."""
|
||||
from django.db import migrations
|
||||
|
||||
# (arcana, suit, number, name, slug, correspondence, group, icon, keywords_upright, keywords_reversed)
|
||||
FIORENTINE_CARDS = [
|
||||
("MAJOR","",0,"The Fool","the-fool","","","",["beginnings","spontaneity","freedom"],["recklessness","naivety","risk"]),
|
||||
("MAJOR","",1,"The Magician","the-magician","","","",["willpower","skill","resourcefulness"],["manipulation","untapped potential","deceit"]),
|
||||
("MAJOR","",2,"The High Priestess","the-high-priestess","","","",["intuition","mystery","inner knowledge"],["secrets","disconnection","withdrawal"]),
|
||||
("MAJOR","",3,"The Empress","the-empress","","","",["fertility","abundance","nurturing"],["dependence","smothering","creative block"]),
|
||||
("MAJOR","",4,"The Emperor","the-emperor","","","",["authority","structure","stability"],["rigidity","domination","inflexibility"]),
|
||||
("MAJOR","",5,"The Hierophant","the-hierophant","","","",["tradition","conformity","institutions"],["rebellion","unconventionality","challenge"]),
|
||||
("MAJOR","",6,"The Lovers","the-lovers","","","",["love","harmony","choice"],["disharmony","imbalance","misalignment"]),
|
||||
("MAJOR","",7,"The Chariot","the-chariot","","","",["control","willpower","victory"],["aggression","lack of direction","defeat"]),
|
||||
("MAJOR","",8,"Strength","strength","","","",["courage","patience","compassion"],["self-doubt","weakness","insecurity"]),
|
||||
("MAJOR","",9,"The Hermit","the-hermit","","","",["introspection","guidance","solitude"],["isolation","loneliness","withdrawal"]),
|
||||
("MAJOR","",10,"Wheel of Fortune","wheel-of-fortune","","","",["change","cycles","fate"],["bad luck","resistance","clinging to control"]),
|
||||
("MAJOR","",11,"Justice","justice","","","",["fairness","truth","cause and effect"],["injustice","dishonesty","avoidance"]),
|
||||
("MAJOR","",12,"The Hanged Man","the-hanged-man","","","",["pause","surrender","new perspective"],["stalling","resistance","indecision"]),
|
||||
("MAJOR","",13,"Death","death","","","",["endings","transition","transformation"],["fear of change","stagnation","resistance"]),
|
||||
("MAJOR","",14,"Temperance","temperance","","","",["balance","patience","moderation"],["imbalance","excess","lack of harmony"]),
|
||||
("MAJOR","",15,"The Devil","the-devil","","","",["bondage","materialism","shadow self"],["detachment","freedom","releasing control"]),
|
||||
("MAJOR","",16,"The Tower","the-tower","","","",["sudden change","upheaval","revelation"],["avoidance","fear of change","delaying disaster"]),
|
||||
("MAJOR","",17,"The Star","the-star","","","",["hope","renewal","inspiration"],["despair","insecurity","hopelessness"]),
|
||||
("MAJOR","",18,"The Moon","the-moon","","","",["illusion","fear","the unconscious"],["confusion","misinterpretation","clarity"]),
|
||||
("MAJOR","",19,"The Sun","the-sun","","","",["positivity","success","vitality"],["negativity","depression","sadness"]),
|
||||
("MAJOR","",20,"Judgement","judgement","","","",["reflection","reckoning","absolution"],["self-doubt","lack of self-awareness","loathing"]),
|
||||
("MAJOR","",21,"The World","the-world","","","",["completion","integration","accomplishment"],["incompletion","no closure","shortcuts"]),
|
||||
("MINOR","CUPS",1,"Ace of Cups","ace-of-cups","","","",["new feelings","intuition","opportunity"],["blocked creativity","emptiness","hesitation"]),
|
||||
("MINOR","CUPS",2,"Two of Cups","two-of-cups","","","",["partnership","unity","celebration"],["imbalance","broken bonds","misalignment"]),
|
||||
("MINOR","CUPS",3,"Three of Cups","three-of-cups","","","",["creativity","community","abundance"],["independence","isolation","looking inward"]),
|
||||
("MINOR","CUPS",4,"Four of Cups","four-of-cups","","","",["contemplation","apathy","reevaluation"],["withdrawal","boredom","seeking motivation"]),
|
||||
("MINOR","CUPS",5,"Five of Cups","five-of-cups","","","",["loss","grief","disappointment"],["acceptance","moving on","forgiveness"]),
|
||||
("MINOR","CUPS",6,"Six of Cups","six-of-cups","","","",["nostalgia","reunion","joy"],["living in the past","naivety","unrealistic"]),
|
||||
("MINOR","CUPS",7,"Seven of Cups","seven-of-cups","","","",["illusion","fantasy","wishful thinking"],["alignment","clarity","sobriety"]),
|
||||
("MINOR","CUPS",8,"Eight of Cups","eight-of-cups","","","",["disappointment","abandonment","walking away"],["hopelessness","aimlessness","stagnation"]),
|
||||
("MINOR","CUPS",9,"Nine of Cups","nine-of-cups","","","",["contentment","fulfilment","satisfaction"],["inner happiness","materialism","indulgence"]),
|
||||
("MINOR","CUPS",10,"Ten of Cups","ten-of-cups","","","",["divine love","bliss","fulfilment"],["inner happiness","alignment","personal values"]),
|
||||
("MINOR","CUPS",11,"Page of Cups","page-of-cups","","","",["sensitivity","creativity","intuition"],["insecurity","emotional immaturity","creative blocks"]),
|
||||
("MINOR","CUPS",12,"Knight of Cups","knight-of-cups","","","",["compassion","romanticism","diplomacy"],["moodiness","emotional manipulation","deception"]),
|
||||
("MINOR","CUPS",13,"Queen of Cups","queen-of-cups","","","",["compassion","empathy","nurturing"],["emotional insecurity","over-giving","neglect"]),
|
||||
("MINOR","CUPS",14,"King of Cups","king-of-cups","","","",["emotional maturity","diplomacy","wisdom"],["manipulation","moodiness","coldness"]),
|
||||
("MINOR","PENTACLES",1,"Ace of Pentacles","ace-of-pentacles","","","",["opportunity","new venture","manifestation"],["lost opportunity","lack of planning","scarcity"]),
|
||||
("MINOR","PENTACLES",2,"Two of Pentacles","two-of-pentacles","","","",["juggling resources","flexibility","fun"],["imbalance","disorganisation","overwhelm"]),
|
||||
("MINOR","PENTACLES",3,"Three of Pentacles","three-of-pentacles","","","",["teamwork","building","apprenticeship"],["lack of teamwork","disharmony","misalignment"]),
|
||||
("MINOR","PENTACLES",4,"Four of Pentacles","four-of-pentacles","","","",["stability","security","conservation"],["greed","stinginess","possessiveness"]),
|
||||
("MINOR","PENTACLES",5,"Five of Pentacles","five-of-pentacles","","","",["isolation","insecurity","worry"],["recovery from loss","overcoming hardship"]),
|
||||
("MINOR","PENTACLES",6,"Six of Pentacles","six-of-pentacles","","","",["generosity","charity","community"],["strings attached","power dynamics","inequality"]),
|
||||
("MINOR","PENTACLES",7,"Seven of Pentacles","seven-of-pentacles","","","",["hard work","perseverance","diligence"],["lack of reward","laziness","low quality"]),
|
||||
("MINOR","PENTACLES",8,"Eight of Pentacles","eight-of-pentacles","","","",["apprenticeship","education","skill"],["perfectionism","misdirected activity","misuse"]),
|
||||
("MINOR","PENTACLES",9,"Nine of Pentacles","nine-of-pentacles","","","",["abundance","luxury","self-sufficiency"],["overindulgence","superficiality","materialism"]),
|
||||
("MINOR","PENTACLES",10,"Ten of Pentacles","ten-of-pentacles","","","",["wealth","financial security","achievement"],["financial failure","greed","lost success"]),
|
||||
("MINOR","PENTACLES",11,"Page of Pentacles","page-of-pentacles","","","",["ambition","diligence","management"],["underhandedness","greediness","unethical"]),
|
||||
("MINOR","PENTACLES",12,"Knight of Pentacles","knight-of-pentacles","","","",["hard work","productivity","routine"],["laziness","obsession with work","burnout"]),
|
||||
("MINOR","PENTACLES",13,"Queen of Pentacles","queen-of-pentacles","","","",["nurturing","practical","abundance"],["financial dependence","smothering","insecurity"]),
|
||||
("MINOR","PENTACLES",14,"King of Pentacles","king-of-pentacles","","","",["abundance","prosperity","security"],["greed","indulgence","sensual obsession"]),
|
||||
("MINOR","SWORDS",1,"Ace of Swords","ace-of-swords","","","",["raw power","breakthrough","clarity"],["confusion","brutality","mental chaos"]),
|
||||
("MINOR","SWORDS",2,"Two of Swords","two-of-swords","","","",["difficult choices","stalemate","truce"],["indecision","lies","confusion"]),
|
||||
("MINOR","SWORDS",3,"Three of Swords","three-of-swords","","","",["heartbreak","sorrow","grief"],["recovery","forgiveness","moving on"]),
|
||||
("MINOR","SWORDS",4,"Four of Swords","four-of-swords","","","",["rest","restoration","retreat"],["restlessness","burnout","illness"]),
|
||||
("MINOR","SWORDS",5,"Five of Swords","five-of-swords","","","",["defeat","change","transition"],["resistance to change","inability to move"]),
|
||||
("MINOR","SWORDS",6,"Six of Swords","six-of-swords","","","",["victory","success","ambition"],["an eye for an eye","dishonour","manipulation"]),
|
||||
("MINOR","SWORDS",7,"Seven of Swords","seven-of-swords","","","",["deception","trickery","tactics"],["imposter syndrome","coming clean","rethinking"]),
|
||||
("MINOR","SWORDS",8,"Eight of Swords","eight-of-swords","","","",["restriction","isolation","imprisonment"],["self-limiting beliefs","inner critic","opening up"]),
|
||||
("MINOR","SWORDS",9,"Nine of Swords","nine-of-swords","","","",["anxiety","worry","fear"],["recovery from anxiety","inner turmoil","secrets"]),
|
||||
("MINOR","SWORDS",10,"Ten of Swords","ten-of-swords","","","",["ruin","painful endings","loss"],["recovery","regeneration","resisting an end"]),
|
||||
("MINOR","SWORDS",11,"Page of Swords","page-of-swords","","","",["new ideas","mental agility","curiosity"],["manipulation","all talk no action","ruthlessness"]),
|
||||
("MINOR","SWORDS",12,"Knight of Swords","knight-of-swords","","","",["action","impulsiveness","ambition"],["no direction","disregard for consequences"]),
|
||||
("MINOR","SWORDS",13,"Queen of Swords","queen-of-swords","","","",["clarity","directness","structure"],["coldness","cruelty","manipulation"]),
|
||||
("MINOR","SWORDS",14,"King of Swords","king-of-swords","","","",["mental clarity","truth","authority"],["abuse of power","manipulation","coldness"]),
|
||||
("MINOR","WANDS",1,"Ace of Wands","ace-of-wands","","","",["inspiration","new venture","spark"],["delays","lack of motivation","false start"]),
|
||||
("MINOR","WANDS",2,"Two of Wands","two-of-wands","","","",["planning","progress","decisions"],["impatience","lack of planning","hesitation"]),
|
||||
("MINOR","WANDS",3,"Three of Wands","three-of-wands","","","",["expansion","foresight","enterprise"],["obstacles","lack of foresight","delays"]),
|
||||
("MINOR","WANDS",4,"Four of Wands","four-of-wands","","","",["celebration","harmony","homecoming"],["lack of support","transience","home conflicts"]),
|
||||
("MINOR","WANDS",5,"Five of Wands","five-of-wands","","","",["conflict","competition","tension"],["avoiding conflict","compromise","truce"]),
|
||||
("MINOR","WANDS",6,"Six of Wands","six-of-wands","","","",["victory","recognition","progress"],["excess pride","lack of recognition","fall"]),
|
||||
("MINOR","WANDS",7,"Seven of Wands","seven-of-wands","","","",["challenge","courage","competition"],["anxiety","giving up","overwhelmed"]),
|
||||
("MINOR","WANDS",8,"Eight of Wands","eight-of-wands","","","",["rapid action","adventure","change"],["haste","scattered energy","delays"]),
|
||||
("MINOR","WANDS",9,"Nine of Wands","nine-of-wands","","","",["resilience","persistence","last stand"],["exhaustion","giving up","surrender"]),
|
||||
("MINOR","WANDS",10,"Ten of Wands","ten-of-wands","","","",["completion","celebration","travel"],["burdens","oppression","carrying too much"]),
|
||||
("MINOR","WANDS",11,"Page of Wands","page-of-wands","","","",["exploration","enthusiasm","adventure"],["hasty decisions","scattered energy","immaturity"]),
|
||||
("MINOR","WANDS",12,"Knight of Wands","knight-of-wands","","","",["energy","passion","adventure"],["scattered energy","frustration","aggression"]),
|
||||
("MINOR","WANDS",13,"Queen of Wands","queen-of-wands","","","",["confidence","independence","courage"],["selfishness","jealousy","insecurity"]),
|
||||
("MINOR","WANDS",14,"King of Wands","king-of-wands","","","",["big picture","leadership","vision"],["impulsiveness","haste","overconfidence"]),
|
||||
]
|
||||
|
||||
|
||||
def seed(apps, schema_editor):
|
||||
DeckVariant = apps.get_model('epic', 'DeckVariant')
|
||||
TarotCard = apps.get_model('epic', 'TarotCard')
|
||||
|
||||
deck = DeckVariant.objects.create(
|
||||
name='Fiorentine Minchiate',
|
||||
slug='fiorentine-minchiate',
|
||||
card_count=78,
|
||||
is_default=False,
|
||||
)
|
||||
for arcana, suit, number, name, slug, correspondence, group, icon, kw_up, kw_rev in FIORENTINE_CARDS:
|
||||
TarotCard.objects.create(
|
||||
deck_variant=deck,
|
||||
arcana=arcana,
|
||||
suit=suit or None,
|
||||
number=number,
|
||||
name=name,
|
||||
slug=slug,
|
||||
correspondence=correspondence,
|
||||
group=group,
|
||||
icon=icon,
|
||||
keywords_upright=kw_up,
|
||||
keywords_reversed=kw_rev,
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0002_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(seed, migrations.RunPython.noop),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 6.0 on 2026-03-15 00:32
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0003_roominvite'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='room',
|
||||
name='gate_status',
|
||||
field=models.CharField(choices=[('GATHERING', 'GATHERING GAMERS'), ('OPEN', 'Open'), ('RENEWAL_DUE', 'Renewal Due')], default='GATHERING', max_length=20),
|
||||
),
|
||||
]
|
||||
184
src/apps/epic/migrations/0004_seed_earthman_deck.py
Normal file
184
src/apps/epic/migrations/0004_seed_earthman_deck.py
Normal file
@@ -0,0 +1,184 @@
|
||||
"""Seed the Earthman deck: DeckVariant + 50 major + 56 minor/middle arcana (106 cards total)."""
|
||||
from django.db import migrations
|
||||
|
||||
# Major arcana
|
||||
# (number, name, slug, group, correspondence, icon,
|
||||
# reversal, levity_qualifier, gravity_qualifier,
|
||||
# levity_emanation, gravity_emanation, levity_reversal, gravity_reversal,
|
||||
# mechanisms, articulations, keywords_upright, keywords_reversed, cautions)
|
||||
EM_MAJOR = [
|
||||
(0,"The Nomad","the-nomad","","The Fool / Il Matto","fa-hat-cowboy-side","","","","","","","",[], [],["beginnings","spontaneity","freedom"],["recklessness","naivety","risk"],[]),
|
||||
(1,"The Schizo","the-schizo","Pope/Horseman","Magician","fa-hat-wizard","Territoriality","Enlightened","Engraven","","","","",[], [],["willpower","skill","resourcefulness"],["manipulation","untapped potential","deceit"],["This card will reverse into <span class=\"card-ref\">I. The Pervert</span> when it comes under dominion of <span class=\"card-ref\">II. The Occultist</span>, which in turn reverses into <span class=\"card-ref\">II. Pestilence</span>.","This card will reverse into <span class=\"card-ref\">I. The Paranoiac</span> when it comes under dominion of <span class=\"card-ref\">III. The Despot</span>, which in turn reverses into <span class=\"card-ref\">III. War</span>.","This card will reverse into <span class=\"card-ref\">I. The Neurotic</span> when it comes under dominion of <span class=\"card-ref\">IV. The Capitalist</span>, which in turn reverses into <span class=\"card-ref\">IV. Famine</span>.","This card will reverse into <span class=\"card-ref\">I. The Suicidal</span> when it comes under dominion of <span class=\"card-ref\">V. The Fascist</span>, which in turn reverses into <span class=\"card-ref\">V. Death</span>."]),
|
||||
(2,"The Occultist","the-occultist","Pope/Horseman","High Priestess","fa-hand-dots","Territoriality","Enlightened","Engraven","","","","",[], [],["intuition","mystery","inner knowledge"],["secrets","disconnection","withdrawal"],[]),
|
||||
(3,"The Despot","the-despot","Pope/Horseman","Empress","fa-hand-dots","Despotism","Enlightened","Engraven","","","","",[], [],["fertility","abundance","nurturing"],["dependence","smothering","creative block"],[]),
|
||||
(4,"The Capitalist","the-capitalist","Pope/Horseman","Emperor","fa-hand-dots","Capitalism","Enlightened","Engraven","","","","",[], [],["authority","structure","stability"],["rigidity","domination","inflexibility"],[]),
|
||||
(5,"The Fascist","the-fascist","Pope/Horseman","Hierophant","fa-hand-dots","Fascism","Enlightened","Engraven","","","","",[], [],["tradition","conformity","institutions"],["rebellion","unconventionality","challenge"],[]),
|
||||
(6,"Controlled Folly","controlled-folly","Implicit Virtues","Fortitude","fa-hand-dots","","","","","","","",[], [],["courage","patience","compassion"],["self-doubt","weakness","insecurity"],[]),
|
||||
(7,"Not Doing","not-doing","Implicit Virtues","Temperance","fa-hand-dots","","","","","","","",[], [],["fairness","truth","cause and effect"],["injustice","dishonesty","avoidance"],[]),
|
||||
(8,"Losing Self-Importance","losing-self-importance","Implicit Virtues","Justice","fa-hand-dots","","","","","","","",[], [],["balance","patience","moderation"],["imbalance","excess","lack of harmony"],[]),
|
||||
(9,"Erasing Personal History","erasing-personal-history","Implicit Virtues","Prudence","fa-hand-dots","","","","","","","",[], [],[],[],[]),
|
||||
(10,"Space","space-em","Elements","Chariot","fa-hand-dots","Nexus","Kinetic","Potential","","","","",[], [],[],[],[]),
|
||||
(11,"Time","time-em","Elements","Hermit","fa-hand-dots","Tempo","Kinetic","Potential","","","","",[], [],[],[],[]),
|
||||
(12,"Stone","stone-em","Elements","Earth","fa-hand-dots","Ossum","Kinetic","Potential","","","","",[], [],[],[],[]),
|
||||
(13,"Fire","fire-em","Elements","Fire","fa-hand-dots","Ardor","Kinetic","Potential","","","","",[], [],[],[],[]),
|
||||
(14,"Water","water-em","Elements","Water","fa-hand-dots","Humor","Kinetic","Potential","","","","",[], [],[],[],[]),
|
||||
(15,"Air","air-em","Elements","Air","fa-hand-dots","Pneuma","Kinetic","Potential","","","","",[], [],[],[],[]),
|
||||
(16,"Disco Inferno","disco-inferno","Realms","Devil","fa-hand-dots","Shame","Deasil","Widdershins","","","","",[], [],["sudden change","upheaval","revelation"],["avoidance","fear of change","delaying disaster"],[]),
|
||||
(17,"Torre Terrestre","torre-terrestre","Realms","Tower","fa-hand-dots","Guilt","Deasil","Widdershins","","","","",[], [],[],[],[]),
|
||||
(18,"Fantasia Celestia","fantasia-celestia","Realms","Wheel of Fortune","fa-hand-dots","Anxiety","Deasil","Widdershins","","","","",[], [],[],[],[]),
|
||||
(19,"Stalking","stalking","Explicit Virtues","Charity","fa-hand-dots","","","","","","","",[], [],["love","harmony","choice"],["disharmony","imbalance","misalignment"],[]),
|
||||
(20,"Dreaming","dreaming","Explicit Virtues","Faith","fa-hand-dots","","","","","","","",[], [],[],[],[]),
|
||||
(21,"Intent","intent","Explicit Virtues","Hope","fa-hand-dots","","","","","","","",[], [],[],[],[]),
|
||||
(22,"Aries","aries","Zodiac Signs & Houses","Aries","fa-hand-dots","House of Self","Precessional","Recessional","","","","",[], [],[],[],[]),
|
||||
(23,"Taurus","taurus","Zodiac Signs & Houses","Taurus","fa-hand-dots","House of Worth","Precessional","Recessional","","","","",[], [],[],[],[]),
|
||||
(24,"Gemini","gemini","Zodiac Signs & Houses","Gemini","fa-hand-dots","House of Education","Precessional","Recessional","","","","",[], [],[],[],[]),
|
||||
(25,"Cancer","cancer","Zodiac Signs & Houses","Cancer","fa-hand-dots","House of Family","Precessional","Recessional","","","","",[], [],[],[],[]),
|
||||
(26,"Leo","leo","Zodiac Signs & Houses","Leo","fa-hand-dots","House of Creation","Precessional","Recessional","","","","",[], [],[],[],[]),
|
||||
(27,"Virgo","virgo","Zodiac Signs & Houses","Virgo","fa-hand-dots","House of Ritual","Precessional","Recessional","","","","",[], [],[],[],[]),
|
||||
(28,"Libra","libra","Zodiac Signs & Houses","Libra","fa-hand-dots","House of Cooperation","Precessional","Recessional","","","","",[], [],[],[],[]),
|
||||
(29,"Scorpio","scorpio","Zodiac Signs & Houses","Scorpio","fa-hand-dots","House of Regeneration","Precessional","Recessional","","","","",[], [],[],[],[]),
|
||||
(30,"Sagittarius","sagittarius","Zodiac Signs & Houses","Sagittarius","fa-hand-dots","House of Enterprise","Precessional","Recessional","","","","",[], [],[],[],[]),
|
||||
(31,"Capricorn","capricorn","Zodiac Signs & Houses","Capricorn","fa-hand-dots","House of Career","Precessional","Recessional","","","","",[], [],[],[],[]),
|
||||
(32,"Aquarius","aquarius","Zodiac Signs & Houses","Aquarius","fa-hand-dots","House of Reward","Precessional","Recessional","","","","",[], [],[],[],[]),
|
||||
(33,"Pisces","pisces","Zodiac Signs & Houses","Pisces","fa-hand-dots","House of Reprisal","Precessional","Recessional","","","","",[], [],[],[],[]),
|
||||
(34,"Animal Powers","animal-powers","Lunars","Hanged Man","fa-hand-dots","Patrilineage","Centrifugal","Centripetal","","","","",[], [],["pause","surrender","new perspective"],["stalling","resistance","indecision"],[]),
|
||||
(35,"Seeded Earth","seeded-earth","Lunars","Death","fa-hand-dots","Matrilineage","Centrifugal","Centripetal","","","","",[], [],["endings","transition","transformation"],["fear of change","stagnation","resistance"],[]),
|
||||
(36,"The Twins of Pluto","twins-of-pluto","Lunars","Pluto","fa-hand-dots","","Prograde","Retrograde","","","","",[], [],[],[],[]),
|
||||
(37,"Neptune","neptune","Planets","Neptune","fa-hand-dots","","Prograde","Retrograde","","","","",[], [],[],[],[]),
|
||||
(38,"Uranus","uranus","Planets","Uranus","fa-hand-dots","","Prograde","Retrograde","","","","",[], [],[],[],[]),
|
||||
(39,"Saturn","saturn","Planets","Saturn","fa-hand-dots","","Prograde","Retrograde","","","","",[], [],[],[],[]),
|
||||
(40,"Jupiter","jupiter","Planets","Jupiter","fa-hand-dots","","Prograde","Retrograde","","","","",[], [],[],[],[]),
|
||||
(41,"The Asteroid Belt","the-asteroid-belt","Planets","","","Ouroboros","Prograde","Retrograde","","","","",[], [],[],[],[]),
|
||||
(42,"Mars","mars","Planets","Mars","fa-hand-dots","","Prograde","Retrograde","","","","",[], [],[],[],[]),
|
||||
(43,"Venus","venus","Planets","Venus","fa-hand-dots","","Prograde","Retrograde","","","","",[], [],[],[],[]),
|
||||
(44,"Mercury","mercury","Planets","Mercury","fa-hand-dots","","Prograde","Retrograde","","","","",[], [],[],[],[]),
|
||||
(45,"The Polestar","the-polestar","Inner Rings","Star","fa-hand-dots","","Precessional","Recessional","","","","",[], [],["hope","renewal","inspiration"],["despair","insecurity","hopelessness"],[]),
|
||||
(46,"The Antichthon","the-antichthon","Inner Rings","Moon","fa-hand-dots","","Waxing","Waning","","","","",[], [],["illusion","fear","the unconscious"],["confusion","misinterpretation","clarity"],[]),
|
||||
(47,"The Corestar","the-corestar","Inner Rings","Sun","fa-hand-dots","","Inclining","Declining","","","","",[], [],["positivity","success","vitality"],["negativity","depression","sadness"],[]),
|
||||
(48,"Father Sky / Mother Sea","father-sky-mother-sea","","World","fa-hand-dots","","","","Father Sky","Mother Sea","The Storm","The Flood",[], [],["completion","integration","accomplishment"],["incompletion","no closure","shortcuts"],[]),
|
||||
(49,"The Effulgent Mould of Man / The Devouring Eagle","effulgent-mould-devouring-eagle","","Trumpets","fa-hand-dots","","","","The Effulgent Mould of Man","The Devouring Eagle","","",[], [],["reflection","reckoning","absolution"],["self-doubt","lack of self-awareness","loathing"],[]),
|
||||
]
|
||||
|
||||
# Minor/Middle arcana
|
||||
# (arcana, suit, number, name, slug, keywords_upright, keywords_reversed)
|
||||
EM_MINOR = [
|
||||
("MINOR","BRANDS",1,"Ace of Brands","ace-of-wands-em",["inspiration","new venture","spark"],["delays","lack of motivation","false start"]),
|
||||
("MINOR","BRANDS",2,"Two of Brands","two-of-wands-em",["planning","progress","decisions"],["impatience","lack of planning","hesitation"]),
|
||||
("MINOR","BRANDS",3,"Three of Brands","three-of-wands-em",["expansion","foresight","enterprise"],["obstacles","lack of foresight","delays"]),
|
||||
("MINOR","BRANDS",4,"Four of Brands","four-of-wands-em",["celebration","harmony","homecoming"],["lack of support","transience","home conflicts"]),
|
||||
("MINOR","BRANDS",5,"Five of Brands","five-of-wands-em",["conflict","competition","tension"],["avoiding conflict","compromise","truce"]),
|
||||
("MINOR","BRANDS",6,"Six of Brands","six-of-wands-em",["victory","recognition","progress"],["excess pride","lack of recognition","fall"]),
|
||||
("MINOR","BRANDS",7,"Seven of Brands","seven-of-wands-em",["challenge","courage","competition"],["anxiety","giving up","overwhelmed"]),
|
||||
("MINOR","BRANDS",8,"Eight of Brands","eight-of-wands-em",["rapid action","adventure","change"],["haste","scattered energy","delays"]),
|
||||
("MINOR","BRANDS",9,"Nine of Brands","nine-of-wands-em",["resilience","persistence","last stand"],["exhaustion","giving up","surrender"]),
|
||||
("MINOR","BRANDS",10,"Ten of Brands","ten-of-wands-em",["completion","celebration","travel"],["burdens","oppression","carrying too much"]),
|
||||
("MIDDLE","BRANDS",11,"Maid of Brands","maid-of-wands-em",["exploration","enthusiasm","adventure"],["hasty decisions","scattered energy","immaturity"]),
|
||||
("MIDDLE","BRANDS",12,"Jack of Brands","jack-of-wands-em",["energy","passion","adventure"],["scattered energy","frustration","aggression"]),
|
||||
("MIDDLE","BRANDS",13,"Queen of Brands","queen-of-wands-em",["confidence","independence","courage"],["selfishness","jealousy","insecurity"]),
|
||||
("MIDDLE","BRANDS",14,"King of Brands","king-of-wands-em",["big picture","leadership","vision"],["impulsiveness","haste","overconfidence"]),
|
||||
("MINOR","GRAILS",1,"Ace of Grails","ace-of-cups-em",["new feelings","intuition","opportunity"],["blocked creativity","emptiness","hesitation"]),
|
||||
("MINOR","GRAILS",2,"Two of Grails","two-of-cups-em",["partnership","unity","celebration"],["imbalance","broken bonds","misalignment"]),
|
||||
("MINOR","GRAILS",3,"Three of Grails","three-of-cups-em",["creativity","community","abundance"],["independence","isolation","looking inward"]),
|
||||
("MINOR","GRAILS",4,"Four of Grails","four-of-cups-em",["contemplation","apathy","reevaluation"],["withdrawal","boredom","seeking motivation"]),
|
||||
("MINOR","GRAILS",5,"Five of Grails","five-of-cups-em",["loss","grief","disappointment"],["acceptance","moving on","forgiveness"]),
|
||||
("MINOR","GRAILS",6,"Six of Grails","six-of-cups-em",["nostalgia","reunion","joy"],["living in the past","naivety","unrealistic"]),
|
||||
("MINOR","GRAILS",7,"Seven of Grails","seven-of-cups-em",["illusion","fantasy","wishful thinking"],["alignment","clarity","sobriety"]),
|
||||
("MINOR","GRAILS",8,"Eight of Grails","eight-of-cups-em",["disappointment","abandonment","walking away"],["hopelessness","aimlessness","stagnation"]),
|
||||
("MINOR","GRAILS",9,"Nine of Grails","nine-of-cups-em",["contentment","fulfilment","satisfaction"],["inner happiness","materialism","indulgence"]),
|
||||
("MINOR","GRAILS",10,"Ten of Grails","ten-of-cups-em",["divine love","bliss","fulfilment"],["inner happiness","alignment","personal values"]),
|
||||
("MIDDLE","GRAILS",11,"Maid of Grails","maid-of-cups-em",["sensitivity","creativity","intuition"],["insecurity","emotional immaturity","creative blocks"]),
|
||||
("MIDDLE","GRAILS",12,"Jack of Grails","jack-of-cups-em",["compassion","romanticism","diplomacy"],["moodiness","emotional manipulation","deception"]),
|
||||
("MIDDLE","GRAILS",13,"Queen of Grails","queen-of-cups-em",["compassion","empathy","nurturing"],["emotional insecurity","over-giving","neglect"]),
|
||||
("MIDDLE","GRAILS",14,"King of Grails","king-of-cups-em",["emotional maturity","diplomacy","wisdom"],["manipulation","moodiness","coldness"]),
|
||||
("MINOR","BLADES",1,"Ace of Blades","ace-of-swords-em",["raw power","breakthrough","clarity"],["confusion","brutality","mental chaos"]),
|
||||
("MINOR","BLADES",2,"Two of Blades","two-of-swords-em",["difficult choices","stalemate","truce"],["indecision","lies","confusion"]),
|
||||
("MINOR","BLADES",3,"Three of Blades","three-of-swords-em",["heartbreak","sorrow","grief"],["recovery","forgiveness","moving on"]),
|
||||
("MINOR","BLADES",4,"Four of Blades","four-of-swords-em",["rest","restoration","retreat"],["restlessness","burnout","illness"]),
|
||||
("MINOR","BLADES",5,"Five of Blades","five-of-swords-em",["defeat","change","transition"],["resistance to change","inability to move"]),
|
||||
("MINOR","BLADES",6,"Six of Blades","six-of-swords-em",["victory","success","ambition"],["an eye for an eye","dishonour","manipulation"]),
|
||||
("MINOR","BLADES",7,"Seven of Blades","seven-of-swords-em",["deception","trickery","tactics"],["imposter syndrome","coming clean","rethinking"]),
|
||||
("MINOR","BLADES",8,"Eight of Blades","eight-of-swords-em",["restriction","isolation","imprisonment"],["self-limiting beliefs","inner critic","opening up"]),
|
||||
("MINOR","BLADES",9,"Nine of Blades","nine-of-swords-em",["anxiety","worry","fear"],["recovery from anxiety","inner turmoil","secrets"]),
|
||||
("MINOR","BLADES",10,"Ten of Blades","ten-of-swords-em",["ruin","painful endings","loss"],["recovery","regeneration","resisting an end"]),
|
||||
("MIDDLE","BLADES",11,"Maid of Blades","maid-of-swords-em",["new ideas","mental agility","curiosity"],["manipulation","all talk no action","ruthlessness"]),
|
||||
("MIDDLE","BLADES",12,"Jack of Blades","jack-of-swords-em",["action","impulsiveness","ambition"],["no direction","disregard for consequences"]),
|
||||
("MIDDLE","BLADES",13,"Queen of Blades","queen-of-swords-em",["clarity","directness","structure"],["coldness","cruelty","manipulation"]),
|
||||
("MIDDLE","BLADES",14,"King of Blades","king-of-swords-em",["mental clarity","truth","authority"],["abuse of power","manipulation","coldness"]),
|
||||
("MINOR","CROWNS",1,"Ace of Crowns","ace-of-crowns-em",["opportunity","new venture","manifestation"],["lost opportunity","lack of planning","scarcity"]),
|
||||
("MINOR","CROWNS",2,"Two of Crowns","two-of-crowns-em",["juggling resources","flexibility","fun"],["imbalance","disorganisation","overwhelm"]),
|
||||
("MINOR","CROWNS",3,"Three of Crowns","three-of-crowns-em",["teamwork","building","apprenticeship"],["lack of teamwork","disharmony","misalignment"]),
|
||||
("MINOR","CROWNS",4,"Four of Crowns","four-of-crowns-em",["stability","security","conservation"],["greed","stinginess","possessiveness"]),
|
||||
("MINOR","CROWNS",5,"Five of Crowns","five-of-crowns-em",["isolation","insecurity","worry"],["recovery from loss","overcoming hardship"]),
|
||||
("MINOR","CROWNS",6,"Six of Crowns","six-of-crowns-em",["generosity","charity","community"],["strings attached","power dynamics","inequality"]),
|
||||
("MINOR","CROWNS",7,"Seven of Crowns","seven-of-crowns-em",["hard work","perseverance","diligence"],["lack of reward","laziness","low quality"]),
|
||||
("MINOR","CROWNS",8,"Eight of Crowns","eight-of-crowns-em",["apprenticeship","education","skill"],["perfectionism","misdirected activity","misuse"]),
|
||||
("MINOR","CROWNS",9,"Nine of Crowns","nine-of-crowns-em",["abundance","luxury","self-sufficiency"],["overindulgence","superficiality","materialism"]),
|
||||
("MINOR","CROWNS",10,"Ten of Crowns","ten-of-crowns-em",["wealth","financial security","achievement"],["financial failure","greed","lost success"]),
|
||||
("MIDDLE","CROWNS",11,"Maid of Crowns","maid-of-crowns-em",["ambition","diligence","management"],["underhandedness","greediness","unethical"]),
|
||||
("MIDDLE","CROWNS",12,"Jack of Crowns","jack-of-crowns-em",["hard work","productivity","routine"],["laziness","obsession with work","burnout"]),
|
||||
("MIDDLE","CROWNS",13,"Queen of Crowns","queen-of-crowns-em",["nurturing","practical","abundance"],["financial dependence","smothering","insecurity"]),
|
||||
("MIDDLE","CROWNS",14,"King of Crowns","king-of-crowns-em",["abundance","prosperity","security"],["greed","indulgence","sensual obsession"]),
|
||||
]
|
||||
|
||||
|
||||
def seed(apps, schema_editor):
|
||||
DeckVariant = apps.get_model('epic', 'DeckVariant')
|
||||
TarotCard = apps.get_model('epic', 'TarotCard')
|
||||
|
||||
deck = DeckVariant.objects.create(
|
||||
name='Earthman',
|
||||
slug='earthman',
|
||||
card_count=106,
|
||||
is_default=True,
|
||||
)
|
||||
|
||||
for (number, name, slug, group, correspondence, icon,
|
||||
reversal, levity_qualifier, gravity_qualifier,
|
||||
levity_emanation, gravity_emanation, levity_reversal, gravity_reversal,
|
||||
mechanisms, articulations, kw_up, kw_rev, cautions) in EM_MAJOR:
|
||||
TarotCard.objects.create(
|
||||
deck_variant=deck,
|
||||
arcana='MAJOR',
|
||||
suit=None,
|
||||
number=number,
|
||||
name=name,
|
||||
slug=slug,
|
||||
group=group,
|
||||
correspondence=correspondence,
|
||||
icon=icon,
|
||||
reversal=reversal,
|
||||
levity_qualifier=levity_qualifier,
|
||||
gravity_qualifier=gravity_qualifier,
|
||||
levity_emanation=levity_emanation,
|
||||
gravity_emanation=gravity_emanation,
|
||||
levity_reversal=levity_reversal,
|
||||
gravity_reversal=gravity_reversal,
|
||||
mechanisms=mechanisms,
|
||||
articulations=articulations,
|
||||
keywords_upright=kw_up,
|
||||
keywords_reversed=kw_rev,
|
||||
cautions=cautions,
|
||||
)
|
||||
|
||||
for arcana, suit, number, name, slug, kw_up, kw_rev in EM_MINOR:
|
||||
TarotCard.objects.create(
|
||||
deck_variant=deck,
|
||||
arcana=arcana,
|
||||
suit=suit,
|
||||
number=number,
|
||||
name=name,
|
||||
slug=slug,
|
||||
keywords_upright=kw_up,
|
||||
keywords_reversed=kw_rev,
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0003_seed_fiorentine_deck'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(seed, migrations.RunPython.noop),
|
||||
]
|
||||
@@ -1,21 +0,0 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0004_alter_room_gate_status'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='gateslot',
|
||||
name='debited_token_type',
|
||||
field=models.CharField(max_length=8, null=True, blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='gateslot',
|
||||
name='debited_token_expires_at',
|
||||
field=models.DateTimeField(null=True, blank=True),
|
||||
),
|
||||
]
|
||||
92
src/apps/epic/migrations/0005_seed_astro_reference_tables.py
Normal file
92
src/apps/epic/migrations/0005_seed_astro_reference_tables.py
Normal file
@@ -0,0 +1,92 @@
|
||||
"""Seed Sign, Planet, AspectType, and HouseLabel reference tables."""
|
||||
from django.db import migrations
|
||||
|
||||
# (order, name, symbol, element, modality, start_degree)
|
||||
SIGNS = [
|
||||
(0, 'Aries', '♈', 'Fire', 'Cardinal', 0.0),
|
||||
(1, 'Taurus', '♉', 'Earth', 'Fixed', 30.0),
|
||||
(2, 'Gemini', '♊', 'Air', 'Mutable', 60.0),
|
||||
(3, 'Cancer', '♋', 'Water', 'Cardinal', 90.0),
|
||||
(4, 'Leo', '♌', 'Fire', 'Fixed', 120.0),
|
||||
(5, 'Virgo', '♍', 'Earth', 'Mutable', 150.0),
|
||||
(6, 'Libra', '♎', 'Air', 'Cardinal', 180.0),
|
||||
(7, 'Scorpio', '♏', 'Water', 'Fixed', 210.0),
|
||||
(8, 'Sagittarius', '♐', 'Fire', 'Mutable', 240.0),
|
||||
(9, 'Capricorn', '♑', 'Earth', 'Cardinal', 270.0),
|
||||
(10, 'Aquarius', '♒', 'Air', 'Fixed', 300.0),
|
||||
(11, 'Pisces', '♓', 'Water', 'Mutable', 330.0),
|
||||
]
|
||||
|
||||
# (order, name, symbol)
|
||||
PLANETS = [
|
||||
(0, 'Sun', '☉'),
|
||||
(1, 'Moon', '☽'),
|
||||
(2, 'Mercury', '☿'),
|
||||
(3, 'Venus', '♀'),
|
||||
(4, 'Mars', '♂'),
|
||||
(5, 'Jupiter', '♃'),
|
||||
(6, 'Saturn', '♄'),
|
||||
(7, 'Uranus', '♅'),
|
||||
(8, 'Neptune', '♆'),
|
||||
(9, 'Pluto', '♇'),
|
||||
]
|
||||
|
||||
# (name, symbol, angle, orb) — mirrors ASPECTS in pyswiss/apps/charts/calc.py
|
||||
ASPECT_TYPES = [
|
||||
('Conjunction', '☌', 0, 8.0),
|
||||
('Semisextile', '⚺', 30, 4.0),
|
||||
('Semisquare', '∠', 45, 4.0),
|
||||
('Sextile', '⚹', 60, 6.0),
|
||||
('Square', '□', 90, 8.0),
|
||||
('Trine', '△', 120, 8.0),
|
||||
('Sesquiquadrate', '⊼', 135, 4.0),
|
||||
('Quincunx', '⚻', 150, 5.0),
|
||||
('Opposition', '☍', 180, 10.0),
|
||||
]
|
||||
|
||||
# (number, name, keywords)
|
||||
HOUSE_LABELS = [
|
||||
(1, 'Self', 'identity, appearance, first impressions'),
|
||||
(2, 'Worth', 'possessions, values, finances'),
|
||||
(3, 'Education', 'communication, siblings, short journeys'),
|
||||
(4, 'Family', 'home, roots, ancestry'),
|
||||
(5, 'Creation', 'creativity, romance, children, pleasure'),
|
||||
(6, 'Ritual', 'service, health, daily routines'),
|
||||
(7, 'Cooperation', 'partnerships, marriage, open enemies'),
|
||||
(8, 'Regeneration', 'transformation, shared resources, death'),
|
||||
(9, 'Enterprise', 'philosophy, travel, higher learning'),
|
||||
(10, 'Career', 'public life, reputation, authority'),
|
||||
(11, 'Reward', 'friends, groups, aspirations'),
|
||||
(12, 'Reprisal', 'hidden matters, karma, self-undoing'),
|
||||
]
|
||||
|
||||
|
||||
def seed(apps, schema_editor):
|
||||
Sign = apps.get_model('epic', 'Sign')
|
||||
Planet = apps.get_model('epic', 'Planet')
|
||||
AspectType = apps.get_model('epic', 'AspectType')
|
||||
HouseLabel = apps.get_model('epic', 'HouseLabel')
|
||||
|
||||
for order, name, symbol, element, modality, start_degree in SIGNS:
|
||||
Sign.objects.create(order=order, name=name, symbol=symbol,
|
||||
element=element, modality=modality, start_degree=start_degree)
|
||||
|
||||
for order, name, symbol in PLANETS:
|
||||
Planet.objects.create(order=order, name=name, symbol=symbol)
|
||||
|
||||
for name, symbol, angle, orb in ASPECT_TYPES:
|
||||
AspectType.objects.create(name=name, symbol=symbol, angle=angle, orb=orb)
|
||||
|
||||
for number, name, keywords in HOUSE_LABELS:
|
||||
HouseLabel.objects.create(number=number, name=name, keywords=keywords)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0004_seed_earthman_deck'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(seed, migrations.RunPython.noop),
|
||||
]
|
||||
@@ -1,33 +0,0 @@
|
||||
# Generated by Django 6.0 on 2026-03-17 00:14
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0005_gateslot_debited_token_fields'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='room',
|
||||
name='table_status',
|
||||
field=models.CharField(blank=True, choices=[('ROLE_SELECT', 'Role Select'), ('SIG_SELECT', 'Significator Select'), ('IN_GAME', 'In Game')], max_length=20, null=True),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TableSeat',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('slot_number', models.IntegerField()),
|
||||
('role', models.CharField(blank=True, choices=[('PC', 'Player'), ('BC', 'Builder'), ('SC', 'Shepherd'), ('AC', 'Alchemist'), ('NC', 'Narrator'), ('EC', 'Economist')], max_length=2, null=True)),
|
||||
('role_revealed', models.BooleanField(default=False)),
|
||||
('seat_position', models.IntegerField(blank=True, null=True)),
|
||||
('gamer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='table_seats', to=settings.AUTH_USER_MODEL)),
|
||||
('room', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='table_seats', to='epic.room')),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -1,39 +0,0 @@
|
||||
# Generated by Django 6.0 on 2026-03-24 23:33
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0006_table_status_and_table_seat'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='TarotCard',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=100, unique=True)),
|
||||
('arcana', models.CharField(choices=[('MAJOR', 'Major Arcana'), ('MINOR', 'Minor Arcana')], max_length=5)),
|
||||
('suit', models.CharField(blank=True, choices=[('WANDS', 'Wands'), ('CUPS', 'Cups'), ('SWORDS', 'Swords'), ('PENTACLES', 'Pentacles')], max_length=10, null=True)),
|
||||
('number', models.IntegerField()),
|
||||
('slug', models.SlugField(unique=True)),
|
||||
('keywords_upright', models.JSONField(default=list)),
|
||||
('keywords_reversed', models.JSONField(default=list)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['arcana', 'suit', 'number'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TarotDeck',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('drawn_card_ids', models.JSONField(default=list)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('room', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='tarot_deck', to='epic.room')),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -1,164 +0,0 @@
|
||||
from django.db import migrations
|
||||
|
||||
MAJOR_ARCANA = [
|
||||
(0, "The Fool", "the-fool", ["beginnings", "spontaneity", "freedom"], ["recklessness", "naivety", "risk"]),
|
||||
(1, "The Magician", "the-magician", ["willpower", "skill", "resourcefulness"], ["manipulation", "untapped potential", "deceit"]),
|
||||
(2, "The High Priestess", "the-high-priestess", ["intuition", "mystery", "inner knowledge"], ["secrets", "disconnection", "withdrawal"]),
|
||||
(3, "The Empress", "the-empress", ["fertility", "abundance", "nurturing"], ["dependence", "smothering", "creative block"]),
|
||||
(4, "The Emperor", "the-emperor", ["authority", "structure", "stability"], ["rigidity", "domination", "inflexibility"]),
|
||||
(5, "The Hierophant", "the-hierophant", ["tradition", "conformity", "institutions"], ["rebellion", "unconventionality", "challenge"]),
|
||||
(6, "The Lovers", "the-lovers", ["love", "harmony", "choice"], ["disharmony", "imbalance", "misalignment"]),
|
||||
(7, "The Chariot", "the-chariot", ["control", "willpower", "victory"], ["aggression", "lack of direction", "defeat"]),
|
||||
(8, "Strength", "strength", ["courage", "patience", "compassion"], ["self-doubt", "weakness", "insecurity"]),
|
||||
(9, "The Hermit", "the-hermit", ["introspection", "guidance", "solitude"], ["isolation", "loneliness", "withdrawal"]),
|
||||
(10, "Wheel of Fortune", "wheel-of-fortune", ["change", "cycles", "fate"], ["bad luck", "resistance", "clinging to control"]),
|
||||
(11, "Justice", "justice", ["fairness", "truth", "cause and effect"], ["injustice", "dishonesty", "avoidance"]),
|
||||
(12, "The Hanged Man", "the-hanged-man", ["pause", "surrender", "new perspective"], ["stalling", "resistance", "indecision"]),
|
||||
(13, "Death", "death", ["endings", "transition", "transformation"], ["fear of change", "stagnation", "resistance"]),
|
||||
(14, "Temperance", "temperance", ["balance", "patience", "moderation"], ["imbalance", "excess", "lack of harmony"]),
|
||||
(15, "The Devil", "the-devil", ["bondage", "materialism", "shadow self"], ["detachment", "freedom", "releasing control"]),
|
||||
(16, "The Tower", "the-tower", ["sudden change", "upheaval", "revelation"], ["avoidance", "fear of change", "delaying disaster"]),
|
||||
(17, "The Star", "the-star", ["hope", "renewal", "inspiration"], ["despair", "insecurity", "hopelessness"]),
|
||||
(18, "The Moon", "the-moon", ["illusion", "fear", "the unconscious"], ["confusion", "misinterpretation", "clarity"]),
|
||||
(19, "The Sun", "the-sun", ["positivity", "success", "vitality"], ["negativity", "depression", "sadness"]),
|
||||
(20, "Judgement", "judgement", ["reflection", "reckoning", "absolution"], ["self-doubt", "lack of self-awareness", "loathing"]),
|
||||
(21, "The World", "the-world", ["completion", "integration", "accomplishment"], ["incompletion", "no closure", "shortcuts"]),
|
||||
]
|
||||
|
||||
MINOR_SUITS = [
|
||||
("WANDS", "wands"),
|
||||
("CUPS", "cups"),
|
||||
("SWORDS", "swords"),
|
||||
("PENTACLES", "pentacles"),
|
||||
]
|
||||
|
||||
MINOR_NAMES = [
|
||||
(1, "Ace", "ace"),
|
||||
(2, "Two", "two"),
|
||||
(3, "Three", "three"),
|
||||
(4, "Four", "four"),
|
||||
(5, "Five", "five"),
|
||||
(6, "Six", "six"),
|
||||
(7, "Seven", "seven"),
|
||||
(8, "Eight", "eight"),
|
||||
(9, "Nine", "nine"),
|
||||
(10, "Ten", "ten"),
|
||||
(11, "Page", "page"),
|
||||
(12, "Knight", "knight"),
|
||||
(13, "Queen", "queen"),
|
||||
(14, "King", "king"),
|
||||
]
|
||||
|
||||
# Keywords: [suit][number-1] → (upright_list, reversed_list)
|
||||
MINOR_KEYWORDS = {
|
||||
"WANDS": [
|
||||
(["inspiration", "new venture", "spark"], ["delays", "lack of motivation", "false start"]),
|
||||
(["planning", "progress", "decisions"], ["impatience", "lack of planning", "hesitation"]),
|
||||
(["expansion", "foresight", "enterprise"], ["obstacles", "lack of foresight", "delays"]),
|
||||
(["celebration", "harmony", "homecoming"], ["lack of support", "transience", "home conflicts"]),
|
||||
(["conflict", "competition", "tension"], ["avoiding conflict", "compromise", "truce"]),
|
||||
(["victory", "recognition", "progress"], ["excess pride", "lack of recognition", "fall"]),
|
||||
(["challenge", "courage", "competition"], ["anxiety", "giving up", "overwhelmed"]),
|
||||
(["rapid action", "adventure", "change"], ["haste", "scattered energy", "delays"]),
|
||||
(["resilience", "persistence", "last stand"], ["exhaustion", "giving up", "surrender"]),
|
||||
(["completion", "celebration", "travel"], ["burdens", "oppression", "carrying too much"]),
|
||||
(["exploration", "enthusiasm", "adventure"], ["hasty decisions", "scattered energy", "immaturity"]),
|
||||
(["energy", "passion", "adventure"], ["scattered energy", "frustration", "aggression"]),
|
||||
(["confidence", "independence", "courage"], ["selfishness", "jealousy", "insecurity"]),
|
||||
(["big picture", "leadership", "vision"], ["impulsiveness", "haste", "overconfidence"]),
|
||||
],
|
||||
"CUPS": [
|
||||
(["new feelings", "intuition", "opportunity"], ["blocked creativity", "emptiness", "hesitation"]),
|
||||
(["partnership", "unity", "celebration"], ["imbalance", "broken bonds", "misalignment"]),
|
||||
(["creativity", "community", "abundance"], ["independence", "isolation", "looking inward"]),
|
||||
(["contemplation", "apathy", "reevaluation"], ["withdrawal", "boredom", "seeking motivation"]),
|
||||
(["loss", "grief", "disappointment"], ["acceptance", "moving on", "forgiveness"]),
|
||||
(["nostalgia", "reunion", "joy"], ["living in the past", "naivety", "unrealistic"]),
|
||||
(["illusion", "fantasy", "wishful thinking"], ["alignment", "clarity", "sobriety"]),
|
||||
(["disappointment", "abandonment", "walking away"], ["hopelessness", "aimlessness", "stagnation"]),
|
||||
(["contentment", "fulfilment", "satisfaction"], ["inner happiness", "materialism", "indulgence"]),
|
||||
(["divine love", "bliss", "fulfilment"], ["inner happiness", "alignment", "personal values"]),
|
||||
(["sensitivity", "creativity", "intuition"], ["insecurity", "emotional immaturity", "creative blocks"]),
|
||||
(["compassion", "romanticism", "diplomacy"], ["moodiness", "emotional manipulation", "deception"]),
|
||||
(["compassion", "empathy", "nurturing"], ["emotional insecurity", "over-giving", "neglect"]),
|
||||
(["emotional maturity", "diplomacy", "wisdom"], ["manipulation", "moodiness", "coldness"]),
|
||||
],
|
||||
"SWORDS": [
|
||||
(["raw power", "breakthrough", "clarity"], ["confusion", "brutality", "mental chaos"]),
|
||||
(["difficult choices", "stalemate", "truce"], ["indecision", "lies", "confusion"]),
|
||||
(["heartbreak", "sorrow", "grief"], ["recovery", "forgiveness", "moving on"]),
|
||||
(["rest", "restoration", "retreat"], ["restlessness", "burnout", "illness"]),
|
||||
(["defeat", "change", "transition"], ["resistance to change", "inability to move"]),
|
||||
(["victory", "success", "ambition"], ["an eye for an eye", "dishonour", "manipulation"]),
|
||||
(["deception", "trickery", "tactics"], ["imposter syndrome", "coming clean", "rethinking"]),
|
||||
(["restriction", "isolation", "imprisonment"], ["self-limiting beliefs", "inner critic", "opening up"]),
|
||||
(["anxiety", "worry", "fear"], ["recovery from anxiety", "inner turmoil", "secrets"]),
|
||||
(["ruin", "painful endings", "loss"], ["recovery", "regeneration", "resisting an end"]),
|
||||
(["new ideas", "mental agility", "curiosity"], ["manipulation", "all talk no action", "ruthlessness"]),
|
||||
(["action", "impulsiveness", "ambition"], ["no direction", "disregard for consequences"]),
|
||||
(["clarity", "directness", "structure"], ["coldness", "cruelty", "manipulation"]),
|
||||
(["mental clarity", "truth", "authority"], ["abuse of power", "manipulation", "coldness"]),
|
||||
],
|
||||
"PENTACLES": [
|
||||
(["opportunity", "new venture", "manifestation"], ["lost opportunity", "lack of planning", "scarcity"]),
|
||||
(["juggling resources", "flexibility", "fun"], ["imbalance", "disorganisation", "overwhelm"]),
|
||||
(["teamwork", "building", "apprenticeship"], ["lack of teamwork", "disharmony", "misalignment"]),
|
||||
(["stability", "security", "conservation"], ["greed", "stinginess", "possessiveness"]),
|
||||
(["isolation", "insecurity", "worry"], ["recovery from loss", "overcoming hardship"]),
|
||||
(["generosity", "charity", "community"], ["strings attached", "power dynamics", "inequality"]),
|
||||
(["hard work", "perseverance", "diligence"], ["lack of reward", "laziness", "low quality"]),
|
||||
(["apprenticeship", "education", "skill"], ["perfectionism", "misdirected activity", "misuse"]),
|
||||
(["abundance", "luxury", "self-sufficiency"], ["overindulgence", "superficiality", "materialism"]),
|
||||
(["wealth", "financial security", "achievement"], ["financial failure", "greed", "lost success"]),
|
||||
(["ambition", "diligence", "management"], ["underhandedness", "greediness", "unethical"]),
|
||||
(["hard work", "productivity", "routine"], ["laziness", "obsession with work", "burnout"]),
|
||||
(["nurturing", "practical", "abundance"], ["financial dependence", "smothering", "insecurity"]),
|
||||
(["abundance", "prosperity", "security"], ["greed", "indulgence", "sensual obsession"]),
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def seed_tarot_cards(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
|
||||
# Major Arcana
|
||||
for number, name, slug, upright, reversed_ in MAJOR_ARCANA:
|
||||
TarotCard.objects.create(
|
||||
name=name,
|
||||
arcana="MAJOR",
|
||||
suit=None,
|
||||
number=number,
|
||||
slug=slug,
|
||||
keywords_upright=upright,
|
||||
keywords_reversed=reversed_,
|
||||
)
|
||||
|
||||
# Minor Arcana
|
||||
for suit_code, suit_slug in MINOR_SUITS:
|
||||
for number, rank_name, rank_slug in MINOR_NAMES:
|
||||
upright, reversed_ = MINOR_KEYWORDS[suit_code][number - 1]
|
||||
TarotCard.objects.create(
|
||||
name=f"{rank_name} of {suit_code.capitalize()}",
|
||||
arcana="MINOR",
|
||||
suit=suit_code,
|
||||
number=number,
|
||||
slug=f"{rank_slug}-of-{suit_slug}",
|
||||
keywords_upright=upright,
|
||||
keywords_reversed=reversed_,
|
||||
)
|
||||
|
||||
|
||||
def unseed_tarot_cards(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
TarotCard.objects.all().delete()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0007_tarotcard_tarotdeck"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(seed_tarot_cards, reverse_code=unseed_tarot_cards),
|
||||
]
|
||||
@@ -1,68 +0,0 @@
|
||||
# Generated by Django 6.0 on 2026-03-25 00:48
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0008_seed_tarot_cards'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='DeckVariant',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=100, unique=True)),
|
||||
('slug', models.SlugField(unique=True)),
|
||||
('card_count', models.IntegerField()),
|
||||
('description', models.TextField(blank=True)),
|
||||
('is_default', models.BooleanField(default=False)),
|
||||
],
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='tarotcard',
|
||||
options={'ordering': ['deck_variant', 'arcana', 'suit', 'number']},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tarotcard',
|
||||
name='correspondence',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tarotcard',
|
||||
name='group',
|
||||
field=models.CharField(blank=True, max_length=100),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tarotcard',
|
||||
name='name',
|
||||
field=models.CharField(max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tarotcard',
|
||||
name='slug',
|
||||
field=models.SlugField(max_length=120),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tarotcard',
|
||||
name='suit',
|
||||
field=models.CharField(blank=True, choices=[('WANDS', 'Wands'), ('CUPS', 'Cups'), ('SWORDS', 'Swords'), ('PENTACLES', 'Pentacles'), ('COINS', 'Coins')], max_length=10, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tarotcard',
|
||||
name='deck_variant',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cards', to='epic.deckvariant'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tarotdeck',
|
||||
name='deck_variant',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='active_decks', to='epic.deckvariant'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='tarotcard',
|
||||
unique_together={('deck_variant', 'slug')},
|
||||
),
|
||||
]
|
||||
@@ -1,202 +0,0 @@
|
||||
"""
|
||||
Data migration:
|
||||
1. Create DeckVariant records (Fiorentine Minchiate + Earthman).
|
||||
2. Backfill the 78 existing TarotCards → Fiorentine Minchiate.
|
||||
3. Seed all 108 Earthman cards (52 major + 56 minor).
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
# ── Earthman Major Arcana (52 cards, numbers 0–51) ──────────────────────────
|
||||
# (name, slug, group, correspondence)
|
||||
EARTHMAN_MAJOR = [
|
||||
# ── The Schiz ──────────────────────────────────────────────────────────
|
||||
(0, "The Schiz", "the-schiz", "", "The Fool / Il Matto"),
|
||||
|
||||
# ── The Popes ──────────────────────────────────────────────────────────
|
||||
(1, "Pope I: President", "pope-i-president", "The Popes", "The Magician / Il Bagatto"),
|
||||
(2, "Pope II: Tsar", "pope-ii-tsar", "The Popes", "The Popess / La Papessa"),
|
||||
(3, "Pope III: Chairman", "pope-iii-chairman", "The Popes", "The Empress / L'Imperatrice"),
|
||||
(4, "Pope IV: Emperor", "pope-iv-emperor", "The Popes", "The Emperor / L'Imperatore"),
|
||||
(5, "Pope V: Chancellor", "pope-v-chancellor", "The Popes", "The Pope / Il Papa"),
|
||||
|
||||
# ── The Virtues, Implicit (cardinal / acquired) ────────────────────────
|
||||
(6, "Virtue VI: Controlled Folly", "virtue-vi-controlled-folly", "The Virtues, Implicit", "Fortitude / La Fortezza"),
|
||||
(7, "Virtue VII: Not-Doing", "virtue-vii-not-doing", "The Virtues, Implicit", "Justice / La Giustizia"),
|
||||
(8, "Virtue VIII: Losing Self-Importance","virtue-viii-losing-self-importance","The Virtues, Implicit", "Temperance / La Temperanza"),
|
||||
(9, "Virtue IX: Erasing Personal History","virtue-ix-erasing-personal-history","The Virtues, Implicit", "Prudence / La Prudenza"),
|
||||
|
||||
# ── Wheel ──────────────────────────────────────────────────────────────
|
||||
(10, "Wheel of Fortune", "wheel-of-fortune-em", "", "La Ruota della Fortuna"),
|
||||
|
||||
# ── Solo cards ─────────────────────────────────────────────────────────
|
||||
(11, "The Junkboat", "the-junkboat", "", "The Chariot / Il Carro"),
|
||||
(12, "The Junkman", "the-junkman", "", "The Hanged Man / L'Appeso"),
|
||||
(13, "Death", "death-em", "", "La Morte"),
|
||||
(14, "The Traitor", "the-traitor", "", "The Devil / Il Diavolo"),
|
||||
(15, "Disco Inferno", "disco-inferno", "", "The Tower / La Torre"),
|
||||
(16, "Torre Terrestre", "torre-terrestre", "", "Purgatorio"),
|
||||
(17, "Fantasia Celestia", "fantasia-celestia", "", "Paradiso"),
|
||||
|
||||
# ── The Virtues, Explicit (theological / infused) ─────────────────────
|
||||
(18, "Virtue XVIII: Stalking", "virtue-xviii-stalking", "The Virtues, Explicit", "Love / Charity / La Carità"),
|
||||
(19, "Virtue XIX: Intent", "virtue-xix-intent", "The Virtues, Explicit", "Hope / La Speranza"),
|
||||
(20, "Virtue XX: Dreaming", "virtue-xx-dreaming", "The Virtues, Explicit", "Faith / La Fede"),
|
||||
|
||||
# ── The Elements, Classical ────────────────────────────────────────────
|
||||
(21, "Element XXI: Fire", "element-xxi-fire", "The Elements, Classical", "Ardor [Ar]"),
|
||||
(22, "Element XXII: Earth", "element-xxii-earth", "The Elements, Classical", "Ossum [Om]"),
|
||||
(23, "Element XXIII: Air", "element-xxiii-air", "The Elements, Classical", "Pneuma [Pn]"),
|
||||
(24, "Element XXIV: Water", "element-xxiv-water", "The Elements, Classical", "Humor [Hm]"),
|
||||
|
||||
# ── The Zodiac ─────────────────────────────────────────────────────────
|
||||
(25, "Zodiac XXV: Aries", "zodiac-xxv-aries", "The Zodiac", "The Ram"),
|
||||
(26, "Zodiac XXVI: Taurus", "zodiac-xxvi-taurus", "The Zodiac", "The Bull"),
|
||||
(27, "Zodiac XXVII: Gemini", "zodiac-xxvii-gemini", "The Zodiac", "The Twins"),
|
||||
(28, "Zodiac XXVIII: Cancer", "zodiac-xxviii-cancer", "The Zodiac", "The Crab"),
|
||||
(29, "Zodiac XXIX: Leo", "zodiac-xxix-leo", "The Zodiac", "The Lion"),
|
||||
(30, "Zodiac XXX: Virgo", "zodiac-xxx-virgo", "The Zodiac", "The Maiden"),
|
||||
(31, "Zodiac XXXI: Libra", "zodiac-xxxi-libra", "The Zodiac", "The Scales"),
|
||||
(32, "Zodiac XXXII: Scorpio", "zodiac-xxxii-scorpio", "The Zodiac", "The Scorpion"),
|
||||
(33, "Zodiac XXXIII: Sagittarius", "zodiac-xxxiii-sagittarius", "The Zodiac", "The Archer"),
|
||||
(34, "Zodiac XXXIV: Capricorn", "zodiac-xxxiv-capricorn", "The Zodiac", "The Sea-Goat"),
|
||||
(35, "Zodiac XXXV: Aquarius", "zodiac-xxxv-aquarius", "The Zodiac", "The Water-Bearer"),
|
||||
(36, "Zodiac XXXVI: Pisces", "zodiac-xxxvi-pisces", "The Zodiac", "The Fish"),
|
||||
|
||||
# ── The Elements, Absolute ─────────────────────────────────────────────
|
||||
(37, "Element XXXVII: Time", "element-xxxvii-time", "The Elements, Absolute", "Tempo [Tp]"),
|
||||
(38, "Element XXXVIII: Space", "element-xxxviii-space", "The Elements, Absolute", "Nexus [Nx]"),
|
||||
|
||||
# ── The Wanderers ──────────────────────────────────────────────────────
|
||||
(39, "Wanderer XXXIX: The Polestar", "wanderer-xxxix-polestar", "The Wanderers", "The Star / Le Stelle"),
|
||||
(40, "Wanderer XL: The Antichthon", "wanderer-xl-antichthon", "The Wanderers", "The Moon / La Luna"),
|
||||
(41, "Wanderer XLI: The Corestar", "wanderer-xli-corestar", "The Wanderers", "The Sun / Il Sole"),
|
||||
(42, "Wanderer XLII: Mercury", "wanderer-xlii-mercury", "The Wanderers", "Mercurio"),
|
||||
(43, "Wanderer XLIII: Venus", "wanderer-xliii-venus", "The Wanderers", "Venere"),
|
||||
(44, "Wanderer XLIV: Mars", "wanderer-xliv-mars", "The Wanderers", "Marte"),
|
||||
(45, "Wanderer XLV: Jupiter", "wanderer-xlv-jupiter", "The Wanderers", "Giove"),
|
||||
(46, "Wanderer XLVI: Saturn", "wanderer-xlvi-saturn", "The Wanderers", "Saturno"),
|
||||
(47, "Wanderer XLVII: Uranus", "wanderer-xlvii-uranus", "The Wanderers", "Urano"),
|
||||
(48, "Wanderer XLVIII: Neptune", "wanderer-xlviii-neptune", "The Wanderers", "Nettuno"),
|
||||
(49, "Wanderer XLIX: The King & Queen of Hades", "wanderer-xlix-king-queen-hades", "The Wanderers", "The Binary / Plutone-Proserpina"),
|
||||
|
||||
# ── Finale ─────────────────────────────────────────────────────────────
|
||||
(50, "The Eagle", "the-eagle", "", "Judgement / L'Angelo"),
|
||||
(51, "Divine Calculus", "divine-calculus", "", "The World / Il Mondo"),
|
||||
]
|
||||
|
||||
# ── Earthman Minor Arcana ────────────────────────────────────────────────────
|
||||
# 4 suits × 14 cards. Suits: WANDS / CUPS / SWORDS / COINS
|
||||
# Court cards: Jack (11) / Cavalier (12) / Queen (13) / King (14)
|
||||
EARTHMAN_SUITS = [
|
||||
("WANDS", "wands", "Ardor [Ar] — Fire"),
|
||||
("CUPS", "cups", "Humor [Hm] — Water"),
|
||||
("SWORDS","swords","Pneuma [Pn] — Air"),
|
||||
("COINS", "coins", "Ossum [Om] — Stone"),
|
||||
]
|
||||
|
||||
EARTHMAN_RANKS = [
|
||||
(1, "Ace", "ace"),
|
||||
(2, "2", "two"),
|
||||
(3, "3", "three"),
|
||||
(4, "4", "four"),
|
||||
(5, "5", "five"),
|
||||
(6, "6", "six"),
|
||||
(7, "7", "seven"),
|
||||
(8, "8", "eight"),
|
||||
(9, "9", "nine"),
|
||||
(10, "10", "ten"),
|
||||
(11, "Jack", "jack"),
|
||||
(12, "Cavalier", "cavalier"),
|
||||
(13, "Queen", "queen"),
|
||||
(14, "King", "king"),
|
||||
]
|
||||
|
||||
|
||||
def forward(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
# ── 1. Create DeckVariant records ────────────────────────────────────
|
||||
fiorentine = DeckVariant.objects.create(
|
||||
name="Fiorentine Minchiate",
|
||||
slug="fiorentine-minchiate",
|
||||
card_count=78,
|
||||
description="Standard 78-card Minchiate deck. Alt / lite play mode.",
|
||||
is_default=False,
|
||||
)
|
||||
earthman = DeckVariant.objects.create(
|
||||
name="Earthman Deck",
|
||||
slug="earthman",
|
||||
card_count=108,
|
||||
description=(
|
||||
"Primary 108-card Earthman deck. "
|
||||
"52 Major Arcana (The Schiz through Divine Calculus) "
|
||||
"+ 56 Minor Arcana across Wands, Cups, Swords, Coins."
|
||||
),
|
||||
is_default=True,
|
||||
)
|
||||
|
||||
# ── 2. Backfill existing 78 Fiorentine cards ─────────────────────────
|
||||
TarotCard.objects.filter(deck_variant__isnull=True).update(
|
||||
deck_variant=fiorentine
|
||||
)
|
||||
|
||||
# ── 3. Seed Earthman Major Arcana ────────────────────────────────────
|
||||
for number, name, slug, group, correspondence in EARTHMAN_MAJOR:
|
||||
TarotCard.objects.create(
|
||||
deck_variant=earthman,
|
||||
name=name,
|
||||
arcana="MAJOR",
|
||||
suit=None,
|
||||
number=number,
|
||||
slug=slug,
|
||||
group=group,
|
||||
correspondence=correspondence,
|
||||
keywords_upright=[],
|
||||
keywords_reversed=[],
|
||||
)
|
||||
|
||||
# ── 4. Seed Earthman Minor Arcana ────────────────────────────────────
|
||||
for suit_code, suit_slug, _element in EARTHMAN_SUITS:
|
||||
for number, rank_name, rank_slug in EARTHMAN_RANKS:
|
||||
name = f"{rank_name} of {suit_code.capitalize()}"
|
||||
slug = f"{rank_slug}-of-{suit_slug}-em"
|
||||
TarotCard.objects.create(
|
||||
deck_variant=earthman,
|
||||
name=name,
|
||||
arcana="MINOR",
|
||||
suit=suit_code,
|
||||
number=number,
|
||||
slug=slug,
|
||||
group="",
|
||||
correspondence="",
|
||||
keywords_upright=[],
|
||||
keywords_reversed=[],
|
||||
)
|
||||
|
||||
|
||||
def reverse(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
# Remove Earthman cards and clear FK from Fiorentine cards
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if earthman:
|
||||
TarotCard.objects.filter(deck_variant=earthman).delete()
|
||||
|
||||
fiorentine = DeckVariant.objects.filter(slug="fiorentine-minchiate").first()
|
||||
if fiorentine:
|
||||
TarotCard.objects.filter(deck_variant=fiorentine).update(deck_variant=None)
|
||||
|
||||
DeckVariant.objects.filter(slug__in=["earthman", "fiorentine-minchiate"]).delete()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0009_deckvariant_alter_tarotcard_options_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forward, reverse_code=reverse),
|
||||
]
|
||||
@@ -1,82 +0,0 @@
|
||||
"""
|
||||
Data migration: rename Earthman court cards at positions 11 and 12.
|
||||
|
||||
Old naming (from 0010): Jack (11) / Cavalier (12)
|
||||
New naming: Maid (11) / Jack (12)
|
||||
|
||||
Must rename 11 → Maid first so the "jack-of-*-em" slugs are free
|
||||
before the 12s claim them.
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
SUITS = ["Wands", "Cups", "Swords", "Coins"]
|
||||
|
||||
|
||||
def rename_court_cards(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
# Step 1: Jack (11) → Maid — frees up jack-of-*-em slugs
|
||||
for suit in SUITS:
|
||||
suit_slug = suit.lower()
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, number=11, slug=f"jack-of-{suit_slug}-em"
|
||||
).update(
|
||||
name=f"Maid of {suit}",
|
||||
slug=f"maid-of-{suit_slug}-em",
|
||||
)
|
||||
|
||||
# Step 2: Cavalier (12) → Jack — takes the now-free jack-of-*-em slugs
|
||||
for suit in SUITS:
|
||||
suit_slug = suit.lower()
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, number=12, slug=f"cavalier-of-{suit_slug}-em"
|
||||
).update(
|
||||
name=f"Jack of {suit}",
|
||||
slug=f"jack-of-{suit_slug}-em",
|
||||
)
|
||||
|
||||
|
||||
def reverse_court_cards(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
# Step 1: Jack (12) → Cavalier — frees up jack-of-*-em slugs
|
||||
for suit in SUITS:
|
||||
suit_slug = suit.lower()
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, number=12, slug=f"jack-of-{suit_slug}-em"
|
||||
).update(
|
||||
name=f"Cavalier of {suit}",
|
||||
slug=f"cavalier-of-{suit_slug}-em",
|
||||
)
|
||||
|
||||
# Step 2: Maid (11) → Jack
|
||||
for suit in SUITS:
|
||||
suit_slug = suit.lower()
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, number=11, slug=f"maid-of-{suit_slug}-em"
|
||||
).update(
|
||||
name=f"Jack of {suit}",
|
||||
slug=f"jack-of-{suit_slug}-em",
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0010_seed_deck_variants_and_earthman"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(rename_court_cards, reverse_code=reverse_court_cards),
|
||||
]
|
||||
@@ -1,162 +0,0 @@
|
||||
"""
|
||||
Data migration:
|
||||
1. Rename grouped Earthman major arcana to use group-relative ordinals
|
||||
(e.g. "Virtue VI: Controlled Folly" → "Implicit Virtue 1: Controlled Folly").
|
||||
2. Spell out Earthman minor arcana pip names 2–10
|
||||
(e.g. "2 of Wands" → "Two of Wands").
|
||||
|
||||
Corner ranks (Roman numerals of absolute card number) are a property on the model
|
||||
and are unchanged — this only affects the stored name / slug fields.
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
# ── Major arcana: (new_name, new_slug) keyed by card number ─────────────────
|
||||
|
||||
MAJOR_RENAMES = {
|
||||
# Implicit Virtues (cards 6–9)
|
||||
6: ("Implicit Virtue 1: Controlled Folly", "implicit-virtue-1-controlled-folly"),
|
||||
7: ("Implicit Virtue 2: Not-Doing", "implicit-virtue-2-not-doing"),
|
||||
8: ("Implicit Virtue 3: Losing Self-Importance", "implicit-virtue-3-losing-self-importance"),
|
||||
9: ("Implicit Virtue 4: Erasing Personal History", "implicit-virtue-4-erasing-personal-history"),
|
||||
# Explicit Virtues (cards 18–20)
|
||||
18: ("Explicit Virtue 1: Stalking", "explicit-virtue-1-stalking"),
|
||||
19: ("Explicit Virtue 2: Intent", "explicit-virtue-2-intent"),
|
||||
20: ("Explicit Virtue 3: Dreaming", "explicit-virtue-3-dreaming"),
|
||||
# Classical Elements (cards 21–24)
|
||||
21: ("Classical Element 1: Fire", "classical-element-1-fire"),
|
||||
22: ("Classical Element 2: Earth", "classical-element-2-earth"),
|
||||
23: ("Classical Element 3: Air", "classical-element-3-air"),
|
||||
24: ("Classical Element 4: Water", "classical-element-4-water"),
|
||||
# Zodiac (cards 25–36)
|
||||
25: ("Zodiac 1: Aries", "zodiac-1-aries"),
|
||||
26: ("Zodiac 2: Taurus", "zodiac-2-taurus"),
|
||||
27: ("Zodiac 3: Gemini", "zodiac-3-gemini"),
|
||||
28: ("Zodiac 4: Cancer", "zodiac-4-cancer"),
|
||||
29: ("Zodiac 5: Leo", "zodiac-5-leo"),
|
||||
30: ("Zodiac 6: Virgo", "zodiac-6-virgo"),
|
||||
31: ("Zodiac 7: Libra", "zodiac-7-libra"),
|
||||
32: ("Zodiac 8: Scorpio", "zodiac-8-scorpio"),
|
||||
33: ("Zodiac 9: Sagittarius", "zodiac-9-sagittarius"),
|
||||
34: ("Zodiac 10: Capricorn", "zodiac-10-capricorn"),
|
||||
35: ("Zodiac 11: Aquarius", "zodiac-11-aquarius"),
|
||||
36: ("Zodiac 12: Pisces", "zodiac-12-pisces"),
|
||||
# Absolute Elements (cards 37–38)
|
||||
37: ("Absolute Element 1: Time", "absolute-element-1-time"),
|
||||
38: ("Absolute Element 2: Space", "absolute-element-2-space"),
|
||||
# Wanderers (cards 39–49)
|
||||
39: ("Wanderer 1: The Polestar", "wanderer-1-polestar"),
|
||||
40: ("Wanderer 2: The Antichthon", "wanderer-2-antichthon"),
|
||||
41: ("Wanderer 3: The Corestar", "wanderer-3-corestar"),
|
||||
42: ("Wanderer 4: Mercury", "wanderer-4-mercury"),
|
||||
43: ("Wanderer 5: Venus", "wanderer-5-venus"),
|
||||
44: ("Wanderer 6: Mars", "wanderer-6-mars"),
|
||||
45: ("Wanderer 7: Jupiter", "wanderer-7-jupiter"),
|
||||
46: ("Wanderer 8: Saturn", "wanderer-8-saturn"),
|
||||
47: ("Wanderer 9: Uranus", "wanderer-9-uranus"),
|
||||
48: ("Wanderer 10: Neptune", "wanderer-10-neptune"),
|
||||
49: ("Wanderer 11: The King & Queen of Hades", "wanderer-11-king-queen-hades"),
|
||||
}
|
||||
|
||||
# Original (name, slug) pairs for reversal
|
||||
MAJOR_ORIGINALS = {
|
||||
6: ("Virtue VI: Controlled Folly", "virtue-vi-controlled-folly"),
|
||||
7: ("Virtue VII: Not-Doing", "virtue-vii-not-doing"),
|
||||
8: ("Virtue VIII: Losing Self-Importance", "virtue-viii-losing-self-importance"),
|
||||
9: ("Virtue IX: Erasing Personal History", "virtue-ix-erasing-personal-history"),
|
||||
18: ("Virtue XVIII: Stalking", "virtue-xviii-stalking"),
|
||||
19: ("Virtue XIX: Intent", "virtue-xix-intent"),
|
||||
20: ("Virtue XX: Dreaming", "virtue-xx-dreaming"),
|
||||
21: ("Element XXI: Fire", "element-xxi-fire"),
|
||||
22: ("Element XXII: Earth", "element-xxii-earth"),
|
||||
23: ("Element XXIII: Air", "element-xxiii-air"),
|
||||
24: ("Element XXIV: Water", "element-xxiv-water"),
|
||||
25: ("Zodiac XXV: Aries", "zodiac-xxv-aries"),
|
||||
26: ("Zodiac XXVI: Taurus", "zodiac-xxvi-taurus"),
|
||||
27: ("Zodiac XXVII: Gemini", "zodiac-xxvii-gemini"),
|
||||
28: ("Zodiac XXVIII: Cancer", "zodiac-xxviii-cancer"),
|
||||
29: ("Zodiac XXIX: Leo", "zodiac-xxix-leo"),
|
||||
30: ("Zodiac XXX: Virgo", "zodiac-xxx-virgo"),
|
||||
31: ("Zodiac XXXI: Libra", "zodiac-xxxi-libra"),
|
||||
32: ("Zodiac XXXII: Scorpio", "zodiac-xxxii-scorpio"),
|
||||
33: ("Zodiac XXXIII: Sagittarius", "zodiac-xxxiii-sagittarius"),
|
||||
34: ("Zodiac XXXIV: Capricorn", "zodiac-xxxiv-capricorn"),
|
||||
35: ("Zodiac XXXV: Aquarius", "zodiac-xxxv-aquarius"),
|
||||
36: ("Zodiac XXXVI: Pisces", "zodiac-xxxvi-pisces"),
|
||||
37: ("Element XXXVII: Time", "element-xxxvii-time"),
|
||||
38: ("Element XXXVIII: Space", "element-xxxviii-space"),
|
||||
39: ("Wanderer XXXIX: The Polestar", "wanderer-xxxix-polestar"),
|
||||
40: ("Wanderer XL: The Antichthon", "wanderer-xl-antichthon"),
|
||||
41: ("Wanderer XLI: The Corestar", "wanderer-xli-corestar"),
|
||||
42: ("Wanderer XLII: Mercury", "wanderer-xlii-mercury"),
|
||||
43: ("Wanderer XLIII: Venus", "wanderer-xliii-venus"),
|
||||
44: ("Wanderer XLIV: Mars", "wanderer-xliv-mars"),
|
||||
45: ("Wanderer XLV: Jupiter", "wanderer-xlv-jupiter"),
|
||||
46: ("Wanderer XLVI: Saturn", "wanderer-xlvi-saturn"),
|
||||
47: ("Wanderer XLVII: Uranus", "wanderer-xlvii-uranus"),
|
||||
48: ("Wanderer XLVIII: Neptune", "wanderer-xlviii-neptune"),
|
||||
49: ("Wanderer XLIX: The King & Queen of Hades", "wanderer-xlix-king-queen-hades"),
|
||||
}
|
||||
|
||||
# Pip number → spelled-out word (slugs already use the word form, only name changes)
|
||||
PIP_SPELLINGS = {
|
||||
2: "Two", 3: "Three", 4: "Four", 5: "Five",
|
||||
6: "Six", 7: "Seven", 8: "Eight", 9: "Nine", 10: "Ten",
|
||||
}
|
||||
|
||||
SUITS = ["WANDS", "CUPS", "SWORDS", "COINS"]
|
||||
|
||||
|
||||
def rename_forward(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
# 1. Rename grouped major arcana to group-relative ordinals
|
||||
for number, (new_name, new_slug) in MAJOR_RENAMES.items():
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR", number=number
|
||||
).update(name=new_name, slug=new_slug)
|
||||
|
||||
# 2. Spell out pip names 2–10
|
||||
for number, word in PIP_SPELLINGS.items():
|
||||
for suit in SUITS:
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MINOR", suit=suit, number=number
|
||||
).update(name=f"{word} of {suit.capitalize()}")
|
||||
|
||||
|
||||
def rename_reverse(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
# 1. Restore original major arcana names
|
||||
for number, (old_name, old_slug) in MAJOR_ORIGINALS.items():
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR", number=number
|
||||
).update(name=old_name, slug=old_slug)
|
||||
|
||||
# 2. Restore numeric pip names (slugs unchanged)
|
||||
for number, _word in PIP_SPELLINGS.items():
|
||||
for suit in SUITS:
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MINOR", suit=suit, number=number
|
||||
).update(name=f"{number} of {suit.capitalize()}")
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0011_rename_earthman_court_cards"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(rename_forward, reverse_code=rename_reverse),
|
||||
]
|
||||
@@ -1,55 +0,0 @@
|
||||
"""
|
||||
Data migration: rename Earthman 4th-suit cards from COINS → PENTACLES.
|
||||
|
||||
Updates:
|
||||
- suit field: "COINS" → "PENTACLES"
|
||||
- name: "X of Coins" → "X of Pentacles"
|
||||
- slug: "x-of-coins-em" → "x-of-pentacles-em"
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def coins_to_pentacles(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
cards = TarotCard.objects.filter(deck_variant=earthman, suit="COINS")
|
||||
for card in cards:
|
||||
card.suit = "PENTACLES"
|
||||
card.name = card.name.replace(" of Coins", " of Pentacles")
|
||||
card.slug = card.slug.replace("-of-coins-em", "-of-pentacles-em")
|
||||
card.save(update_fields=["suit", "name", "slug"])
|
||||
|
||||
|
||||
def pentacles_to_coins(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
# Only reverse cards that came from Earthman (identified by -em slug suffix)
|
||||
cards = TarotCard.objects.filter(
|
||||
deck_variant=earthman, suit="PENTACLES", slug__endswith="-em"
|
||||
)
|
||||
for card in cards:
|
||||
card.suit = "COINS"
|
||||
card.name = card.name.replace(" of Pentacles", " of Coins")
|
||||
card.slug = card.slug.replace("-of-pentacles-em", "-of-coins-em")
|
||||
card.save(update_fields=["suit", "name", "slug"])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0012_rename_earthman_major_groups_and_pip_spellings"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(coins_to_pentacles, reverse_code=pentacles_to_coins),
|
||||
]
|
||||
@@ -1,65 +0,0 @@
|
||||
"""
|
||||
Data migration: rename the five Pope cards to use Arabic group-relative ordinals,
|
||||
matching the convention set for other grouped major arcana.
|
||||
|
||||
"Pope I: President" → "Pope 1: President"
|
||||
"Pope II: Tsar" → "Pope 2: Tsar"
|
||||
etc.
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
POPE_RENAMES = {
|
||||
1: ("Pope 1: President", "pope-1-president"),
|
||||
2: ("Pope 2: Tsar", "pope-2-tsar"),
|
||||
3: ("Pope 3: Chairman", "pope-3-chairman"),
|
||||
4: ("Pope 4: Emperor", "pope-4-emperor"),
|
||||
5: ("Pope 5: Chancellor", "pope-5-chancellor"),
|
||||
}
|
||||
|
||||
POPE_ORIGINALS = {
|
||||
1: ("Pope I: President", "pope-i-president"),
|
||||
2: ("Pope II: Tsar", "pope-ii-tsar"),
|
||||
3: ("Pope III: Chairman", "pope-iii-chairman"),
|
||||
4: ("Pope IV: Emperor", "pope-iv-emperor"),
|
||||
5: ("Pope V: Chancellor", "pope-v-chancellor"),
|
||||
}
|
||||
|
||||
|
||||
def rename_forward(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
for number, (new_name, new_slug) in POPE_RENAMES.items():
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR", number=number
|
||||
).update(name=new_name, slug=new_slug)
|
||||
|
||||
|
||||
def rename_reverse(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
for number, (old_name, old_slug) in POPE_ORIGINALS.items():
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR", number=number
|
||||
).update(name=old_name, slug=old_slug)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0013_earthman_coins_to_pentacles"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(rename_forward, reverse_code=rename_reverse),
|
||||
]
|
||||
@@ -1,42 +0,0 @@
|
||||
"""
|
||||
Data migration: rename Earthman card 22 from "Classical Element 2: Earth"
|
||||
to "Classical Element 2: Stone" (Stone = Ossum, the Earthman name for Earth).
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def rename_forward(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR", number=22
|
||||
).update(name="Classical Element 2: Stone", slug="classical-element-2-stone")
|
||||
|
||||
|
||||
def rename_reverse(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR", number=22
|
||||
).update(name="Classical Element 2: Earth", slug="classical-element-2-earth")
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0014_rename_earthman_popes_arabic_ordinals"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(rename_forward, reverse_code=rename_reverse),
|
||||
]
|
||||
@@ -1,63 +0,0 @@
|
||||
"""
|
||||
Data migration: reorder the five Pope cards.
|
||||
|
||||
New assignment (card number → title):
|
||||
1 → Chancellor 2 → President 3 → Tsar 4 → Chairman 5 → Emperor
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
POPE_RENAMES = {
|
||||
1: ("Pope 1: Chancellor", "pope-1-chancellor"),
|
||||
2: ("Pope 2: President", "pope-2-president"),
|
||||
3: ("Pope 3: Tsar", "pope-3-tsar"),
|
||||
4: ("Pope 4: Chairman", "pope-4-chairman"),
|
||||
5: ("Pope 5: Emperor", "pope-5-emperor"),
|
||||
}
|
||||
|
||||
POPE_ORIGINALS = {
|
||||
1: ("Pope 1: President", "pope-1-president"),
|
||||
2: ("Pope 2: Tsar", "pope-2-tsar"),
|
||||
3: ("Pope 3: Chairman", "pope-3-chairman"),
|
||||
4: ("Pope 4: Emperor", "pope-4-emperor"),
|
||||
5: ("Pope 5: Chancellor", "pope-5-chancellor"),
|
||||
}
|
||||
|
||||
|
||||
def rename_forward(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
for number, (new_name, new_slug) in POPE_RENAMES.items():
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR", number=number
|
||||
).update(name=new_name, slug=new_slug)
|
||||
|
||||
|
||||
def rename_reverse(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
for number, (old_name, old_slug) in POPE_ORIGINALS.items():
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR", number=number
|
||||
).update(name=old_name, slug=old_slug)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0015_rename_classical_element_earth_to_stone"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(rename_forward, reverse_code=rename_reverse),
|
||||
]
|
||||
@@ -1,19 +0,0 @@
|
||||
# Generated by Django 6.0 on 2026-03-25 05:46
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0016_reorder_earthman_popes'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='tableseat',
|
||||
name='significator',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='significator_seats', to='epic.tarotcard'),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 6.0 on 2026-04-01 17:37
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0017_tableseat_significator_fk'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='tarotcard',
|
||||
name='suit',
|
||||
field=models.CharField(blank=True, choices=[('WANDS', 'Wands'), ('CUPS', 'Cups'), ('SWORDS', 'Swords'), ('PENTACLES', 'Pentacles')], max_length=10, null=True),
|
||||
),
|
||||
]
|
||||
@@ -1,70 +0,0 @@
|
||||
"""
|
||||
Data migration: rename The Schiz (card 0) and the five Pope cards (cards 1–5)
|
||||
in the Earthman deck.
|
||||
|
||||
0: "The Schiz" → "The Nomad"
|
||||
1: "Pope 1: Chancellor" → "Pope 1: The Schizo"
|
||||
2: "Pope 2: President" → "Pope 2: The Despot"
|
||||
3: "Pope 3: Tsar" → "Pope 3: The Capitalist"
|
||||
4: "Pope 4: Chairman" → "Pope 4: The Fascist"
|
||||
5: "Pope 5: Emperor" → "Pope 5: The War Machine"
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
NEW_NAMES = {
|
||||
0: ("The Nomad", "the-nomad"),
|
||||
1: ("Pope 1: The Schizo", "pope-1-the-schizo"),
|
||||
2: ("Pope 2: The Despot", "pope-2-the-despot"),
|
||||
3: ("Pope 3: The Capitalist", "pope-3-the-capitalist"),
|
||||
4: ("Pope 4: The Fascist", "pope-4-the-fascist"),
|
||||
5: ("Pope 5: The War Machine","pope-5-the-war-machine"),
|
||||
}
|
||||
|
||||
OLD_NAMES = {
|
||||
0: ("The Schiz", "the-schiz"),
|
||||
1: ("Pope 1: Chancellor", "pope-1-chancellor"),
|
||||
2: ("Pope 2: President", "pope-2-president"),
|
||||
3: ("Pope 3: Tsar", "pope-3-tsar"),
|
||||
4: ("Pope 4: Chairman", "pope-4-chairman"),
|
||||
5: ("Pope 5: Emperor", "pope-5-emperor"),
|
||||
}
|
||||
|
||||
|
||||
def rename_forward(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
for number, (new_name, new_slug) in NEW_NAMES.items():
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR", number=number
|
||||
).update(name=new_name, slug=new_slug)
|
||||
|
||||
|
||||
def rename_reverse(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
for number, (old_name, old_slug) in OLD_NAMES.items():
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR", number=number
|
||||
).update(name=old_name, slug=old_slug)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0018_alter_tarotcard_suit"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(rename_forward, reverse_code=rename_reverse),
|
||||
]
|
||||
@@ -1,63 +0,0 @@
|
||||
"""
|
||||
Data migration: rename Pope cards 2–5 in the Earthman deck.
|
||||
|
||||
2: "Pope 2: The Despot" → "Pope 2: The Occultist"
|
||||
3: "Pope 3: The Capitalist" → "Pope 3: The Despot"
|
||||
4: "Pope 4: The Fascist" → "Pope 4: The Capitalist"
|
||||
5: "Pope 5: The War Machine" → "Pope 5: The Fascist"
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
NEW_NAMES = {
|
||||
2: ("Pope 2: The Occultist", "pope-2-the-occultist"),
|
||||
3: ("Pope 3: The Despot", "pope-3-the-despot"),
|
||||
4: ("Pope 4: The Capitalist","pope-4-the-capitalist"),
|
||||
5: ("Pope 5: The Fascist", "pope-5-the-fascist"),
|
||||
}
|
||||
|
||||
OLD_NAMES = {
|
||||
2: ("Pope 2: The Despot", "pope-2-the-despot"),
|
||||
3: ("Pope 3: The Capitalist", "pope-3-the-capitalist"),
|
||||
4: ("Pope 4: The Fascist", "pope-4-the-fascist"),
|
||||
5: ("Pope 5: The War Machine", "pope-5-the-war-machine"),
|
||||
}
|
||||
|
||||
|
||||
def rename_forward(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
for number, (new_name, new_slug) in NEW_NAMES.items():
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR", number=number
|
||||
).update(name=new_name, slug=new_slug)
|
||||
|
||||
|
||||
def rename_reverse(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
for number, (old_name, old_slug) in OLD_NAMES.items():
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR", number=number
|
||||
).update(name=old_name, slug=old_slug)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0019_rename_earthman_schiz_and_popes"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(rename_forward, reverse_code=rename_reverse),
|
||||
]
|
||||
@@ -1,56 +0,0 @@
|
||||
"""
|
||||
Data migration: rename/update six Earthman Major Arcana cards.
|
||||
|
||||
13 name: "Death" → "King Death & the Cosmic Tree"
|
||||
14 name: "The Traitor" → "The Great Hunt"
|
||||
15 correspondence: "The Tower / La Torre" → "The House of the Devil / Inferno"
|
||||
16 correspondence: "Purgatorio" → "The Tower / La Torre / Purgatorio"
|
||||
50 name/slug: "The Eagle" → "The Mould of Man"
|
||||
51 name/slug: "Divine Calculus" → "The Eagle"
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
FORWARD = {
|
||||
13: dict(name="King Death & the Cosmic Tree", slug="king-death-and-the-cosmic-tree"),
|
||||
14: dict(name="The Great Hunt", slug="the-great-hunt"),
|
||||
15: dict(correspondence="The House of the Devil / Inferno"),
|
||||
16: dict(correspondence="The Tower / La Torre / Purgatorio"),
|
||||
50: dict(name="The Mould of Man", slug="the-mould-of-man"),
|
||||
51: dict(name="The Eagle", slug="the-eagle"),
|
||||
}
|
||||
|
||||
REVERSE = {
|
||||
13: dict(name="Death", slug="death-em"),
|
||||
14: dict(name="The Traitor", slug="the-traitor"),
|
||||
15: dict(correspondence="The Tower / La Torre"),
|
||||
16: dict(correspondence="Purgatorio"),
|
||||
50: dict(name="The Eagle", slug="the-eagle"),
|
||||
51: dict(name="Divine Calculus",slug="divine-calculus"),
|
||||
}
|
||||
|
||||
|
||||
def apply(changes):
|
||||
def fn(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
# Process in sorted order so card 50 vacates "the-eagle" slug before card 51 claims it.
|
||||
for number in sorted(changes):
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR", number=number
|
||||
).update(**changes[number])
|
||||
return fn
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0020_rename_earthman_pope_cards_2_5"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(apply(FORWARD), reverse_code=apply(REVERSE)),
|
||||
]
|
||||
@@ -1,31 +0,0 @@
|
||||
# Generated by Django 6.0 on 2026-04-06 00:02
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0021_rename_earthman_major_arcana_batch_2'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='SigReservation',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('role', models.CharField(max_length=2)),
|
||||
('polarity', models.CharField(choices=[('levity', 'Levity'), ('gravity', 'Gravity')], max_length=7)),
|
||||
('reserved_at', models.DateTimeField(auto_now_add=True)),
|
||||
('card', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sig_reservations', to='epic.tarotcard')),
|
||||
('gamer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sig_reservations', to=settings.AUTH_USER_MODEL)),
|
||||
('room', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sig_reservations', to='epic.room')),
|
||||
],
|
||||
options={
|
||||
'constraints': [models.UniqueConstraint(fields=('room', 'gamer'), name='one_sig_reservation_per_gamer_per_room'), models.UniqueConstraint(fields=('room', 'card', 'polarity'), name='one_reservation_per_card_per_polarity_per_room')],
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -1,28 +0,0 @@
|
||||
# Generated by Django 6.0 on 2026-04-06 02:22
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0022_sig_reservation'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='tarotcard',
|
||||
name='icon',
|
||||
field=models.CharField(blank=True, default='', max_length=50),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tarotcard',
|
||||
name='arcana',
|
||||
field=models.CharField(choices=[('MAJOR', 'Major Arcana'), ('MINOR', 'Minor Arcana'), ('MIDDLE', 'Middle Arcana')], max_length=6),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tarotcard',
|
||||
name='suit',
|
||||
field=models.CharField(blank=True, choices=[('WANDS', 'Wands'), ('CUPS', 'Cups'), ('SWORDS', 'Swords'), ('PENTACLES', 'Pentacles'), ('CROWNS', 'Crowns')], max_length=10, null=True),
|
||||
),
|
||||
]
|
||||
@@ -1,46 +0,0 @@
|
||||
"""
|
||||
Data migration: rename Earthman 4th-suit cards from PENTACLES → CROWNS.
|
||||
|
||||
Updates for every Earthman card where suit="PENTACLES":
|
||||
- suit: "PENTACLES" → "CROWNS"
|
||||
- name: " of Pentacles" → " of Crowns"
|
||||
- slug: "pentacles" → "crowns"
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def pentacles_to_crowns(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
for card in TarotCard.objects.filter(deck_variant=earthman, suit="PENTACLES"):
|
||||
card.suit = "CROWNS"
|
||||
card.name = card.name.replace(" of Pentacles", " of Crowns")
|
||||
card.slug = card.slug.replace("pentacles", "crowns")
|
||||
card.save(update_fields=["suit", "name", "slug"])
|
||||
|
||||
|
||||
def crowns_to_pentacles(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
for card in TarotCard.objects.filter(deck_variant=earthman, suit="CROWNS"):
|
||||
card.suit = "PENTACLES"
|
||||
card.name = card.name.replace(" of Crowns", " of Pentacles")
|
||||
card.slug = card.slug.replace("crowns", "pentacles")
|
||||
card.save(update_fields=["suit", "name", "slug"])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0023_tarotcard_icon_alter_tarotcard_arcana_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(pentacles_to_crowns, reverse_code=crowns_to_pentacles),
|
||||
]
|
||||
@@ -1,62 +0,0 @@
|
||||
"""
|
||||
Data migration: Earthman deck — court cards and major arcana icons.
|
||||
|
||||
1. Court cards (numbers 11–14, all suits): arcana "MINOR" → "MIDDLE"
|
||||
2. Major arcana icons (stored in TarotCard.icon):
|
||||
0 (Nomad) → fa-hat-cowboy-side
|
||||
1 (Schizo) → fa-hat-wizard
|
||||
2–51 (rest) → fa-hand-dots
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
MAJOR_ICONS = {
|
||||
0: "fa-hat-cowboy-side",
|
||||
1: "fa-hat-wizard",
|
||||
}
|
||||
DEFAULT_MAJOR_ICON = "fa-hand-dots"
|
||||
|
||||
|
||||
def forward(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
# Court cards → MIDDLE
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MINOR", number__in=[11, 12, 13, 14]
|
||||
).update(arcana="MIDDLE")
|
||||
|
||||
# Major arcana icons
|
||||
for card in TarotCard.objects.filter(deck_variant=earthman, arcana="MAJOR"):
|
||||
card.icon = MAJOR_ICONS.get(card.number, DEFAULT_MAJOR_ICON)
|
||||
card.save(update_fields=["icon"])
|
||||
|
||||
|
||||
def backward(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MIDDLE", number__in=[11, 12, 13, 14]
|
||||
).update(arcana="MINOR")
|
||||
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR"
|
||||
).update(icon="")
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0024_earthman_pentacles_to_crowns"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forward, reverse_code=backward),
|
||||
]
|
||||
@@ -1,154 +0,0 @@
|
||||
"""
|
||||
Data migration — Earthman deck:
|
||||
1. Rename three suit codes (and card names) for Earthman cards:
|
||||
WANDS → BRANDS (Wands → Brands)
|
||||
CUPS → GRAILS (Cups → Grails)
|
||||
SWORDS → BLADES (Swords → Blades)
|
||||
CROWNS stays CROWNS.
|
||||
2. Copy keywords_upright / keywords_reversed from the Fiorentine Minchiate
|
||||
deck to corresponding Earthman cards:
|
||||
• Major: explicit number-to-number map based on card correspondences.
|
||||
• Minor/Middle: same number, suit mapped (BRANDS→WANDS, GRAILS→CUPS,
|
||||
BLADES→SWORDS, CROWNS→PENTACLES). Cards with no Fiorentine counterpart
|
||||
stay with empty keyword lists.
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
# ── 1. Suit rename map ────────────────────────────────────────────────────────
|
||||
|
||||
SUIT_RENAMES = {
|
||||
"WANDS": "BRANDS",
|
||||
"CUPS": "GRAILS",
|
||||
"SWORDS": "BLADES",
|
||||
}
|
||||
|
||||
# ── 2. Major arcana: Earthman number → Fiorentine number ─────────────────────
|
||||
# Cards without a Fiorentine counterpart are omitted (keywords stay empty).
|
||||
|
||||
MAJOR_KEYWORD_MAP = {
|
||||
0: 0, # The Schiz → The Fool
|
||||
1: 1, # Pope I (President) → The Magician
|
||||
2: 2, # Pope II (Tsar) → The High Priestess
|
||||
3: 3, # Pope III (Chairman) → The Empress
|
||||
4: 4, # Pope IV (Emperor) → The Emperor
|
||||
5: 5, # Pope V (Chancellor) → The Hierophant
|
||||
6: 8, # Virtue VI (Controlled Folly) → Strength
|
||||
7: 11, # Virtue VII (Not-Doing) → Justice
|
||||
8: 14, # Virtue VIII (Losing Self-Importance) → Temperance
|
||||
# 9: Prudence — no Fiorentine equivalent
|
||||
10: 10, # Wheel of Fortune → Wheel of Fortune
|
||||
11: 7, # The Junkboat → The Chariot
|
||||
12: 12, # The Junkman → The Hanged Man
|
||||
13: 13, # Death → Death
|
||||
14: 15, # The Traitor → The Devil
|
||||
15: 16, # Disco Inferno → The Tower
|
||||
# 16: Torre Terrestre (Purgatory) — no equivalent
|
||||
# 17: Fantasia Celestia (Paradise) — no equivalent
|
||||
18: 6, # Virtue XVIII (Stalking) → The Lovers
|
||||
# 19: Virtue XIX (Intent / Hope) — no equivalent
|
||||
# 20: Virtue XX (Dreaming / Faith)— no equivalent
|
||||
# 21–38: Classical Elements + Zodiac — no equivalents
|
||||
39: 17, # Wanderer XXXIX (Polestar) → The Star
|
||||
40: 18, # Wanderer XL (Antichthon) → The Moon
|
||||
41: 19, # Wanderer XLI (Corestar) → The Sun
|
||||
# 42–49: Planets + The Binary — no equivalents
|
||||
50: 20, # The Eagle → Judgement
|
||||
51: 21, # Divine Calculus → The World
|
||||
}
|
||||
|
||||
# ── 3. Minor suit map: Earthman (post-rename) → Fiorentine ───────────────────
|
||||
|
||||
MINOR_SUIT_MAP = {
|
||||
"BRANDS": "WANDS",
|
||||
"GRAILS": "CUPS",
|
||||
"BLADES": "SWORDS",
|
||||
"CROWNS": "PENTACLES",
|
||||
}
|
||||
|
||||
|
||||
def forward(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
|
||||
try:
|
||||
earthman = DeckVariant.objects.get(slug="earthman")
|
||||
fiorentine = DeckVariant.objects.get(slug="fiorentine-minchiate")
|
||||
except DeckVariant.DoesNotExist:
|
||||
return # decks not seeded — nothing to do
|
||||
|
||||
# ── Step 1: rename Earthman suit codes + card names ───────────────────────
|
||||
for old_suit, new_suit in SUIT_RENAMES.items():
|
||||
old_display = old_suit.capitalize() # e.g. "Wands"
|
||||
new_display = new_suit.capitalize() # e.g. "Brands"
|
||||
cards = TarotCard.objects.filter(deck_variant=earthman, suit=old_suit)
|
||||
for card in cards:
|
||||
card.name = card.name.replace(f" of {old_display}", f" of {new_display}")
|
||||
card.suit = new_suit
|
||||
card.save()
|
||||
|
||||
# ── Step 2: copy major arcana keywords ───────────────────────────────────
|
||||
fio_major = {
|
||||
card.number: card
|
||||
for card in TarotCard.objects.filter(deck_variant=fiorentine, arcana="MAJOR")
|
||||
}
|
||||
for em_num, fio_num in MAJOR_KEYWORD_MAP.items():
|
||||
fio_card = fio_major.get(fio_num)
|
||||
if not fio_card:
|
||||
continue
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR", number=em_num
|
||||
).update(
|
||||
keywords_upright=fio_card.keywords_upright,
|
||||
keywords_reversed=fio_card.keywords_reversed,
|
||||
)
|
||||
|
||||
# ── Step 3: copy minor/middle arcana keywords ─────────────────────────────
|
||||
for em_suit, fio_suit in MINOR_SUIT_MAP.items():
|
||||
fio_by_number = {
|
||||
card.number: card
|
||||
for card in TarotCard.objects.filter(deck_variant=fiorentine, suit=fio_suit)
|
||||
}
|
||||
for em_card in TarotCard.objects.filter(deck_variant=earthman, suit=em_suit):
|
||||
fio_card = fio_by_number.get(em_card.number)
|
||||
if fio_card:
|
||||
em_card.keywords_upright = fio_card.keywords_upright
|
||||
em_card.keywords_reversed = fio_card.keywords_reversed
|
||||
em_card.save()
|
||||
|
||||
|
||||
def reverse(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
|
||||
|
||||
# Reverse suit renames
|
||||
reverse_renames = {new: old for old, new in SUIT_RENAMES.items()}
|
||||
for new_suit, old_suit in reverse_renames.items():
|
||||
new_display = new_suit.capitalize()
|
||||
old_display = old_suit.capitalize()
|
||||
cards = TarotCard.objects.filter(deck_variant=earthman, suit=new_suit)
|
||||
for card in cards:
|
||||
card.name = card.name.replace(f" of {new_display}", f" of {old_display}")
|
||||
card.suit = old_suit
|
||||
card.save()
|
||||
|
||||
# Clear all Earthman keywords
|
||||
TarotCard.objects.filter(deck_variant=earthman).update(
|
||||
keywords_upright=[],
|
||||
keywords_reversed=[],
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0025_earthman_middle_arcana_and_major_icons"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forward, reverse_code=reverse),
|
||||
]
|
||||
@@ -1,65 +0,0 @@
|
||||
"""
|
||||
Schema + data migration:
|
||||
1. Add `cautions` JSONField (list, default=[]) to TarotCard.
|
||||
2. Seed The Schizo (Earthman MAJOR #1) with 4 rival-interaction cautions.
|
||||
All other cards default to [] — the UI shows a placeholder when empty.
|
||||
"""
|
||||
from django.db import migrations, models
|
||||
|
||||
SCHIZO_CAUTIONS = [
|
||||
'This card will reverse into <span class="card-ref">The Pervert</span> when it'
|
||||
' comes under dominion of <span class="card-ref">The Occultist</span>, which in turn'
|
||||
' reverses into <span class="card-ref">Pestilence</span>.',
|
||||
|
||||
'This card will reverse into <span class="card-ref">The Paranoiac</span> when it'
|
||||
' comes under dominion of <span class="card-ref">The Despot</span>, which in turn'
|
||||
' reverses into <span class="card-ref">War</span>.',
|
||||
|
||||
'This card will reverse into <span class="card-ref">The Neurotic</span> when it'
|
||||
' comes under dominion of <span class="card-ref">The Capitalist</span>, which in turn'
|
||||
' reverses into <span class="card-ref">Famine</span>.',
|
||||
|
||||
'This card will reverse into <span class="card-ref">The Suicidal</span> when it'
|
||||
' comes under dominion of <span class="card-ref">The Fascist</span>, which in turn'
|
||||
' reverses into <span class="card-ref">Death</span>.',
|
||||
]
|
||||
|
||||
|
||||
def seed_schizo_cautions(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(cautions=SCHIZO_CAUTIONS)
|
||||
|
||||
|
||||
def clear_schizo_cautions(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(cautions=[])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0026_earthman_suit_renames_and_keywords"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="tarotcard",
|
||||
name="cautions",
|
||||
field=models.JSONField(default=list),
|
||||
),
|
||||
migrations.RunPython(seed_schizo_cautions, reverse_code=clear_schizo_cautions),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 6.0 on 2026-04-07 03:09
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0027_tarotcard_cautions'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='tarotcard',
|
||||
name='suit',
|
||||
field=models.CharField(blank=True, choices=[('WANDS', 'Wands'), ('CUPS', 'Cups'), ('SWORDS', 'Swords'), ('PENTACLES', 'Pentacles'), ('CROWNS', 'Crowns'), ('BRANDS', 'Brands'), ('GRAILS', 'Grails'), ('BLADES', 'Blades')], max_length=10, null=True),
|
||||
),
|
||||
]
|
||||
@@ -1,61 +0,0 @@
|
||||
"""
|
||||
Data fix: clear Schizo cautions from The Nomad (number=0) if present,
|
||||
and ensure they land on The Schizo (number=1).
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
SCHIZO_CAUTIONS = [
|
||||
'This card will reverse into <span class="card-ref">I. The Pervert</span> when it'
|
||||
' comes under dominion of <span class="card-ref">II. The Occultist</span>, which in turn'
|
||||
' reverses into <span class="card-ref">II. Pestilence</span>.',
|
||||
|
||||
'This card will reverse into <span class="card-ref">I. The Paranoiac</span> when it'
|
||||
' comes under dominion of <span class="card-ref">III. The Despot</span>, which in turn'
|
||||
' reverses into <span class="card-ref">III. War</span>.',
|
||||
|
||||
'This card will reverse into <span class="card-ref">I. The Neurotic</span> when it'
|
||||
' comes under dominion of <span class="card-ref">IV. The Capitalist</span>, which in turn'
|
||||
' reverses into <span class="card-ref">IV. Famine</span>.',
|
||||
|
||||
'This card will reverse into <span class="card-ref">I. The Suicidal</span> when it'
|
||||
' comes under dominion of <span class="card-ref">V. The Fascist</span>, which in turn'
|
||||
' reverses into <span class="card-ref">V. Death</span>.',
|
||||
]
|
||||
|
||||
|
||||
def forward(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=0
|
||||
).update(cautions=[])
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, arcana="MAJOR", number=1
|
||||
).update(cautions=SCHIZO_CAUTIONS)
|
||||
|
||||
|
||||
def reverse(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(cautions=[])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0028_alter_tarotcard_suit"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forward, reverse_code=reverse),
|
||||
]
|
||||
@@ -1,23 +0,0 @@
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0029_fix_schizo_cautions'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='sigreservation',
|
||||
name='seat',
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name='sig_reservation',
|
||||
to='epic.tableseat',
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -1,33 +0,0 @@
|
||||
# Generated by Django 6.0 on 2026-04-09 04:53
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0030_sigreservation_seat_fk'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='room',
|
||||
name='sig_select_started_at',
|
||||
field=models.DateTimeField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='sigreservation',
|
||||
name='countdown_remaining',
|
||||
field=models.IntegerField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='sigreservation',
|
||||
name='ready',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='room',
|
||||
name='table_status',
|
||||
field=models.CharField(blank=True, choices=[('ROLE_SELECT', 'Role Select'), ('SIG_SELECT', 'Significator Select'), ('SKY_SELECT', 'Sky Select'), ('IN_GAME', 'In Game')], max_length=20, null=True),
|
||||
),
|
||||
]
|
||||
@@ -1,65 +0,0 @@
|
||||
# Generated by Django 6.0 on 2026-04-14 05:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0031_sig_ready_sky_select'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='AspectType',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=20, unique=True)),
|
||||
('symbol', models.CharField(max_length=5)),
|
||||
('angle', models.PositiveSmallIntegerField()),
|
||||
('orb', models.FloatField()),
|
||||
],
|
||||
options={
|
||||
'ordering': ['angle'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='HouseLabel',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('number', models.PositiveSmallIntegerField(unique=True)),
|
||||
('name', models.CharField(max_length=30)),
|
||||
('keywords', models.CharField(blank=True, max_length=100)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['number'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Planet',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=20, unique=True)),
|
||||
('symbol', models.CharField(max_length=5)),
|
||||
('order', models.PositiveSmallIntegerField(unique=True)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['order'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Sign',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=20, unique=True)),
|
||||
('symbol', models.CharField(max_length=5)),
|
||||
('element', models.CharField(choices=[('Fire', 'Fire'), ('Earth', 'Earth'), ('Air', 'Air'), ('Water', 'Water')], max_length=5)),
|
||||
('modality', models.CharField(choices=[('Cardinal', 'Cardinal'), ('Fixed', 'Fixed'), ('Mutable', 'Mutable')], max_length=8)),
|
||||
('order', models.PositiveSmallIntegerField(unique=True)),
|
||||
('start_degree', models.FloatField()),
|
||||
],
|
||||
options={
|
||||
'ordering': ['order'],
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -1,106 +0,0 @@
|
||||
"""
|
||||
Data migration: seed Sign, Planet, AspectType, and HouseLabel tables.
|
||||
|
||||
These are stable astrological reference rows — never user-edited.
|
||||
The data matches the constants in pyswiss/apps/charts/calc.py so that
|
||||
the proxy view and D3 wheel share a single source of truth.
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
# ── Signs ────────────────────────────────────────────────────────────────────
|
||||
# (order, name, symbol, element, modality, start_degree)
|
||||
SIGNS = [
|
||||
(0, 'Aries', '♈', 'Fire', 'Cardinal', 0.0),
|
||||
(1, 'Taurus', '♉', 'Earth', 'Fixed', 30.0),
|
||||
(2, 'Gemini', '♊', 'Air', 'Mutable', 60.0),
|
||||
(3, 'Cancer', '♋', 'Water', 'Cardinal', 90.0),
|
||||
(4, 'Leo', '♌', 'Fire', 'Fixed', 120.0),
|
||||
(5, 'Virgo', '♍', 'Earth', 'Mutable', 150.0),
|
||||
(6, 'Libra', '♎', 'Air', 'Cardinal', 180.0),
|
||||
(7, 'Scorpio', '♏', 'Water', 'Fixed', 210.0),
|
||||
(8, 'Sagittarius', '♐', 'Fire', 'Mutable', 240.0),
|
||||
(9, 'Capricorn', '♑', 'Earth', 'Cardinal', 270.0),
|
||||
(10, 'Aquarius', '♒', 'Air', 'Fixed', 300.0),
|
||||
(11, 'Pisces', '♓', 'Water', 'Mutable', 330.0),
|
||||
]
|
||||
|
||||
# ── Planets ───────────────────────────────────────────────────────────────────
|
||||
# (order, name, symbol)
|
||||
PLANETS = [
|
||||
(0, 'Sun', '☉'),
|
||||
(1, 'Moon', '☽'),
|
||||
(2, 'Mercury', '☿'),
|
||||
(3, 'Venus', '♀'),
|
||||
(4, 'Mars', '♂'),
|
||||
(5, 'Jupiter', '♃'),
|
||||
(6, 'Saturn', '♄'),
|
||||
(7, 'Uranus', '♅'),
|
||||
(8, 'Neptune', '♆'),
|
||||
(9, 'Pluto', '♇'),
|
||||
]
|
||||
|
||||
# ── Aspect types ──────────────────────────────────────────────────────────────
|
||||
# (name, symbol, angle, orb) — mirrors ASPECTS constant in pyswiss calc.py
|
||||
ASPECT_TYPES = [
|
||||
('Conjunction', '☌', 0, 8.0),
|
||||
('Sextile', '⚹', 60, 6.0),
|
||||
('Square', '□', 90, 8.0),
|
||||
('Trine', '△', 120, 8.0),
|
||||
('Opposition', '☍', 180, 10.0),
|
||||
]
|
||||
|
||||
# ── House labels (distinctions) ───────────────────────────────────────────────
|
||||
# (number, name, keywords)
|
||||
HOUSE_LABELS = [
|
||||
(1, 'Self', 'identity, appearance, first impressions'),
|
||||
(2, 'Worth', 'possessions, values, finances'),
|
||||
(3, 'Education', 'communication, siblings, short journeys'),
|
||||
(4, 'Family', 'home, roots, ancestry'),
|
||||
(5, 'Creation', 'creativity, romance, children, pleasure'),
|
||||
(6, 'Ritual', 'service, health, daily routines'),
|
||||
(7, 'Cooperation', 'partnerships, marriage, open enemies'),
|
||||
(8, 'Regeneration', 'transformation, shared resources, death'),
|
||||
(9, 'Enterprise', 'philosophy, travel, higher learning'),
|
||||
(10, 'Career', 'public life, reputation, authority'),
|
||||
(11, 'Reward', 'friends, groups, aspirations'),
|
||||
(12, 'Reprisal', 'hidden matters, karma, self-undoing'),
|
||||
]
|
||||
|
||||
|
||||
def forward(apps, schema_editor):
|
||||
Sign = apps.get_model('epic', 'Sign')
|
||||
Planet = apps.get_model('epic', 'Planet')
|
||||
AspectType = apps.get_model('epic', 'AspectType')
|
||||
HouseLabel = apps.get_model('epic', 'HouseLabel')
|
||||
|
||||
for order, name, symbol, element, modality, start_degree in SIGNS:
|
||||
Sign.objects.create(
|
||||
order=order, name=name, symbol=symbol,
|
||||
element=element, modality=modality, start_degree=start_degree,
|
||||
)
|
||||
|
||||
for order, name, symbol in PLANETS:
|
||||
Planet.objects.create(order=order, name=name, symbol=symbol)
|
||||
|
||||
for name, symbol, angle, orb in ASPECT_TYPES:
|
||||
AspectType.objects.create(name=name, symbol=symbol, angle=angle, orb=orb)
|
||||
|
||||
for number, name, keywords in HOUSE_LABELS:
|
||||
HouseLabel.objects.create(number=number, name=name, keywords=keywords)
|
||||
|
||||
|
||||
def reverse(apps, schema_editor):
|
||||
for model_name in ('Sign', 'Planet', 'AspectType', 'HouseLabel'):
|
||||
apps.get_model('epic', model_name).objects.all().delete()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0032_astro_reference_tables'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forward, reverse_code=reverse),
|
||||
]
|
||||
@@ -1,35 +0,0 @@
|
||||
# Generated by Django 6.0 on 2026-04-14 05:29
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0033_seed_astro_reference_tables'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Character',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('birth_dt', models.DateTimeField(blank=True, null=True)),
|
||||
('birth_lat', models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True)),
|
||||
('birth_lon', models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True)),
|
||||
('birth_place', models.CharField(blank=True, max_length=200)),
|
||||
('house_system', models.CharField(choices=[('O', 'Porphyry'), ('P', 'Placidus'), ('K', 'Koch'), ('W', 'Whole Sign')], default='O', max_length=1)),
|
||||
('chart_data', models.JSONField(blank=True, null=True)),
|
||||
('celtic_cross', models.JSONField(blank=True, null=True)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('confirmed_at', models.DateTimeField(blank=True, null=True)),
|
||||
('retired_at', models.DateTimeField(blank=True, null=True)),
|
||||
('seat', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='characters', to='epic.tableseat')),
|
||||
('significator', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='character_significators', to='epic.tarotcard')),
|
||||
],
|
||||
options={
|
||||
'ordering': ['-created_at'],
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -1,58 +0,0 @@
|
||||
# Generated by Django 6.0 on 2026-04-27 05:11
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0034_character_model'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='tarotcard',
|
||||
name='articulations',
|
||||
field=models.JSONField(default=list),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tarotcard',
|
||||
name='gravity_emanation',
|
||||
field=models.CharField(blank=True, default='', max_length=200),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tarotcard',
|
||||
name='gravity_qualifier',
|
||||
field=models.CharField(blank=True, default='', max_length=100),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tarotcard',
|
||||
name='gravity_reversal',
|
||||
field=models.CharField(blank=True, default='', max_length=200),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tarotcard',
|
||||
name='levity_emanation',
|
||||
field=models.CharField(blank=True, default='', max_length=200),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tarotcard',
|
||||
name='levity_qualifier',
|
||||
field=models.CharField(blank=True, default='', max_length=100),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tarotcard',
|
||||
name='levity_reversal',
|
||||
field=models.CharField(blank=True, default='', max_length=200),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tarotcard',
|
||||
name='mechanisms',
|
||||
field=models.JSONField(default=list),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tarotcard',
|
||||
name='reversal',
|
||||
field=models.CharField(blank=True, default='', max_length=200),
|
||||
),
|
||||
]
|
||||
@@ -1,307 +0,0 @@
|
||||
"""
|
||||
Re-seed the Earthman major arcana from 52 cards (0-51) to 50 cards (0 + 1-49).
|
||||
|
||||
Card 0 (The Nomad) is left completely untouched.
|
||||
|
||||
Changes:
|
||||
DELETE old #10 Wheel of Fortune, #11 The Junkboat, #14 The Great Hunt
|
||||
INSERT new #41 The Asteroid Belt
|
||||
UPDATE all other major arcana with new numbers, names, slugs, groups,
|
||||
correspondences, reversals, and levity/gravity qualifiers.
|
||||
|
||||
Items flagged ⚠ below were not clearly legible from the source image and are
|
||||
left blank; the user should fill them in a follow-up migration.
|
||||
"""
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# UPDATE spec: (current_slug, new_number, new_name, new_slug, new_group,
|
||||
# correspondence, reversal,
|
||||
# levity_qualifier, gravity_qualifier,
|
||||
# levity_emanation, gravity_emanation,
|
||||
# levity_reversal, gravity_reversal)
|
||||
# ---------------------------------------------------------------------------
|
||||
_UPDATES = [
|
||||
# ── Pope/Horseman ──────────────────────────────────────────────────────
|
||||
('pope-1-the-schizo', 1, 'The Schizo',
|
||||
'the-schizo', 'Pope/Horseman',
|
||||
'Territoriality', '',
|
||||
'Enlightened', 'Engraven',
|
||||
'', '', '', ''),
|
||||
|
||||
('pope-2-the-occultist', 2, 'The Occultist',
|
||||
'the-occultist', 'Pope/Horseman',
|
||||
'Territoriality', '',
|
||||
'Enlightened', 'Engraven',
|
||||
'', '', '', ''),
|
||||
|
||||
('pope-3-the-despot', 3, 'The Despot',
|
||||
'the-despot', 'Pope/Horseman',
|
||||
'Despotism', '',
|
||||
'Enlightened', 'Engraven',
|
||||
'', '', '', ''),
|
||||
|
||||
('pope-4-the-capitalist', 4, 'The Capitalist',
|
||||
'the-capitalist', 'Pope/Horseman',
|
||||
'Capitalism', '',
|
||||
'Enlightened', 'Engraven',
|
||||
'', '', '', ''),
|
||||
|
||||
('pope-5-the-fascist', 5, 'The Fascist',
|
||||
'the-fascist', 'Pope/Horseman',
|
||||
'Fascism', '',
|
||||
'Enlightened', 'Engraven',
|
||||
'', '', '', ''),
|
||||
|
||||
# ── Implicit Virtues ───────────────────────────────────────────────────
|
||||
# ⚠ levity/gravity qualifiers not determined
|
||||
('implicit-virtue-1-controlled-folly', 6, 'Controlled Folly',
|
||||
'controlled-folly', 'Implicit Virtues',
|
||||
'Fortitude', '',
|
||||
'', '', '', '', '', ''),
|
||||
|
||||
('implicit-virtue-2-not-doing', 7, 'Not Doing',
|
||||
'not-doing', 'Implicit Virtues',
|
||||
'Temperance', '',
|
||||
'', '', '', '', '', ''),
|
||||
|
||||
('implicit-virtue-3-losing-self-importance', 8, 'Losing Self-Importance',
|
||||
'losing-self-importance', 'Implicit Virtues',
|
||||
'Justice', '',
|
||||
'', '', '', '', '', ''),
|
||||
|
||||
('implicit-virtue-4-erasing-personal-history', 9, 'Erasing Personal History',
|
||||
'erasing-personal-history', 'Implicit Virtues',
|
||||
'Prudence', '',
|
||||
'', '', '', '', '', ''),
|
||||
|
||||
# ── Elements (6) — Absolute elements move here alongside Classical ─────
|
||||
# Space: was Absolute Element 2 (#38), Chariot correspondence is new
|
||||
('absolute-element-2-space', 10, 'Space',
|
||||
'space-em', 'Elements',
|
||||
'Chariot', 'Nexus',
|
||||
'Kinetic', 'Potential',
|
||||
'', '', '', ''),
|
||||
|
||||
# Time: was Absolute Element 1 (#37)
|
||||
# ⚠ Hermit correspondence confirmed; "Hunchback" variant noted in image
|
||||
('absolute-element-1-time', 11, 'Time',
|
||||
'time-em', 'Elements',
|
||||
'Hermit', 'Tempo',
|
||||
'Kinetic', 'Potential',
|
||||
'', '', '', ''),
|
||||
|
||||
# Stone: was Classical Element 2 (#22)
|
||||
('classical-element-2-stone', 12, 'Stone',
|
||||
'stone-em', 'Elements',
|
||||
'Earth', 'Ossum',
|
||||
'Kinetic', 'Potential',
|
||||
'', '', '', ''),
|
||||
|
||||
# Fire: was Classical Element 1 (#21)
|
||||
('classical-element-1-fire', 13, 'Fire',
|
||||
'fire-em', 'Elements',
|
||||
'Fire', 'Ardor',
|
||||
'Kinetic', 'Potential',
|
||||
'', '', '', ''),
|
||||
|
||||
# Water: was Classical Element 4 (#24)
|
||||
('classical-element-4-water', 14, 'Water',
|
||||
'water-em', 'Elements',
|
||||
'Water', 'Humor',
|
||||
'Kinetic', 'Potential',
|
||||
'', '', '', ''),
|
||||
|
||||
# Air: was Classical Element 3 (#23)
|
||||
('classical-element-3-air', 15, 'Air',
|
||||
'air-em', 'Elements',
|
||||
'Air', 'Pneuma',
|
||||
'Kinetic', 'Potential',
|
||||
'', '', '', ''),
|
||||
|
||||
# ── Realms ─────────────────────────────────────────────────────────────
|
||||
('disco-inferno', 16, 'Disco Inferno',
|
||||
'disco-inferno', 'Realms',
|
||||
'Devil', 'Shame',
|
||||
'Deasil', 'Widdershins',
|
||||
'', '', '', ''),
|
||||
|
||||
('torre-terrestre', 17, 'Torre Terrestre',
|
||||
'torre-terrestre', 'Realms',
|
||||
'Tower', 'Guilt',
|
||||
'Deasil', 'Widdershins',
|
||||
'', '', '', ''),
|
||||
|
||||
('fantasia-celestia', 18, 'Fantasia Celestia',
|
||||
'fantasia-celestia', 'Realms',
|
||||
'Wheel of Fortune', 'Anxiety',
|
||||
'Deasil', 'Widdershins',
|
||||
'', '', '', ''),
|
||||
|
||||
# ── Explicit Virtues ───────────────────────────────────────────────────
|
||||
# ⚠ levity/gravity qualifiers not determined
|
||||
# Stalking: was Explicit Virtue 1 (#18, Love/Charity)
|
||||
('explicit-virtue-1-stalking', 19, 'Stalking',
|
||||
'stalking', 'Explicit Virtues',
|
||||
'Charity', '',
|
||||
'', '', '', '', '', ''),
|
||||
|
||||
# Dreaming: was Explicit Virtue 3 (#20, Faith) — same number
|
||||
('explicit-virtue-3-dreaming', 20, 'Dreaming',
|
||||
'dreaming', 'Explicit Virtues',
|
||||
'Faith', '',
|
||||
'', '', '', '', '', ''),
|
||||
|
||||
# Jovent: was Explicit Virtue 2 (#19, Intent/Hope) — renamed
|
||||
('explicit-virtue-2-intent', 21, 'Jovent',
|
||||
'jovent', 'Explicit Virtues',
|
||||
'Hope', '',
|
||||
'', '', '', '', '', ''),
|
||||
|
||||
# ── Zodiac Signs & Houses (renumber 25-36 → 22-33) ────────────────────
|
||||
('zodiac-1-aries', 22, 'Aries', 'aries', 'Zodiac Signs & Houses', 'House of Self', '', 'Precessional', 'Recessional', '', '', '', ''),
|
||||
('zodiac-2-taurus', 23, 'Taurus', 'taurus', 'Zodiac Signs & Houses', 'House of Worth', '', 'Precessional', 'Recessional', '', '', '', ''),
|
||||
('zodiac-3-gemini', 24, 'Gemini', 'gemini', 'Zodiac Signs & Houses', 'House of Education', '', 'Precessional', 'Recessional', '', '', '', ''),
|
||||
('zodiac-4-cancer', 25, 'Cancer', 'cancer', 'Zodiac Signs & Houses', 'House of Family', '', 'Precessional', 'Recessional', '', '', '', ''),
|
||||
('zodiac-5-leo', 26, 'Leo', 'leo', 'Zodiac Signs & Houses', 'House of Creation', '', 'Precessional', 'Recessional', '', '', '', ''),
|
||||
('zodiac-6-virgo', 27, 'Virgo', 'virgo', 'Zodiac Signs & Houses', 'House of Ritual', '', 'Precessional', 'Recessional', '', '', '', ''),
|
||||
('zodiac-7-libra', 28, 'Libra', 'libra', 'Zodiac Signs & Houses', 'House of Cooperation', '', 'Precessional', 'Recessional', '', '', '', ''),
|
||||
('zodiac-8-scorpio', 29, 'Scorpio', 'scorpio', 'Zodiac Signs & Houses', 'House of Regeneration', '', 'Precessional', 'Recessional', '', '', '', ''),
|
||||
('zodiac-9-sagittarius', 30, 'Sagittarius', 'sagittarius', 'Zodiac Signs & Houses', 'House of Enterprise', '', 'Precessional', 'Recessional', '', '', '', ''),
|
||||
('zodiac-10-capricorn', 31, 'Capricorn', 'capricorn', 'Zodiac Signs & Houses', 'House of Career', '', 'Precessional', 'Recessional', '', '', '', ''),
|
||||
('zodiac-11-aquarius', 32, 'Aquarius', 'aquarius', 'Zodiac Signs & Houses', 'House of Reward', '', 'Precessional', 'Recessional', '', '', '', ''),
|
||||
('zodiac-12-pisces', 33, 'Pisces', 'pisces', 'Zodiac Signs & Houses', 'House of Reprisal', '', 'Precessional', 'Recessional', '', '', '', ''),
|
||||
|
||||
# ── Lunars ─────────────────────────────────────────────────────────────
|
||||
# Animal Powers: was The Junkman (#12, Hanged Man) — renamed
|
||||
('the-junkman', 34, 'Animal Powers',
|
||||
'animal-powers', 'Lunars',
|
||||
'Hanged Man', 'Patrilineage',
|
||||
'Centrifugal', 'Centripetal',
|
||||
'', '', '', ''),
|
||||
|
||||
# Seeded Earth: was King Death & the Cosmic Tree (#13, Death) — renamed
|
||||
('king-death-and-the-cosmic-tree', 35, 'Seeded Earth',
|
||||
'seeded-earth', 'Lunars',
|
||||
'Death', 'Matrilineage',
|
||||
'Centrifugal', 'Centripetal',
|
||||
'', '', '', ''),
|
||||
|
||||
# Twins of Pluto: was Wanderer 11 King & Queen of Hades (#49) — renamed
|
||||
('wanderer-11-king-queen-hades', 36, 'The Twins of Pluto',
|
||||
'twins-of-pluto', 'Lunars',
|
||||
'Pluto', '',
|
||||
'Prograde', 'Retrograde',
|
||||
'', '', '', ''),
|
||||
|
||||
# ── Planets ────────────────────────────────────────────────────────────
|
||||
# ⚠ correspondences left blank — image unclear; user to confirm
|
||||
# Reversals: user confirmed all planet cards reverse to same (blank = same)
|
||||
('wanderer-10-neptune', 37, 'Neptune', 'neptune', 'Planets', 'Neptune', '', 'Prograde', 'Retrograde', '', '', '', ''),
|
||||
('wanderer-9-uranus', 38, 'Uranus', 'uranus', 'Planets', 'Uranus', '', 'Prograde', 'Retrograde', '', '', '', ''),
|
||||
('wanderer-8-saturn', 39, 'Saturn', 'saturn', 'Planets', 'Saturn', '', 'Prograde', 'Retrograde', '', '', '', ''),
|
||||
('wanderer-7-jupiter', 40, 'Jupiter', 'jupiter', 'Planets', 'Jupiter', '', 'Prograde', 'Retrograde', '', '', '', ''),
|
||||
# #41 The Asteroid Belt — INSERT separately below
|
||||
('wanderer-6-mars', 42, 'Mars', 'mars', 'Planets', 'Mars', '', 'Prograde', 'Retrograde', '', '', '', ''),
|
||||
('wanderer-5-venus', 43, 'Venus', 'venus', 'Planets', 'Venus', '', 'Prograde', 'Retrograde', '', '', '', ''),
|
||||
('wanderer-4-mercury', 44, 'Mercury', 'mercury', 'Planets', 'Mercury', '', 'Prograde', 'Retrograde', '', '', '', ''),
|
||||
|
||||
# ── Inner Rings ────────────────────────────────────────────────────────
|
||||
# ⚠ Polestar levity/gravity qualifiers not confirmed from image
|
||||
('wanderer-1-polestar', 45, 'The Polestar', 'the-polestar', 'Inner Rings', 'Star', '', '', '', '', '', '', ''),
|
||||
('wanderer-2-antichthon',46, 'The Antichthon', 'the-antichthon', 'Inner Rings', 'Moon', '', 'Waxing', 'Waning', '', '', '', ''),
|
||||
# Corestar: user changed Ascendant→Inclining, Descendent→Declining
|
||||
('wanderer-3-corestar', 47, 'The Corestar', 'the-corestar', 'Inner Rings', 'Sun', '', 'Inclining', 'Declining', '', '', '', ''),
|
||||
|
||||
# ── Polarity-split finals ──────────────────────────────────────────────
|
||||
# 48: The Eagle → Father Sky (levity) / Mother Sea (gravity)
|
||||
('the-eagle', 48, 'Father Sky / Mother Sea',
|
||||
'father-sky-mother-sea', '',
|
||||
'World', '',
|
||||
'', '',
|
||||
'Father Sky', 'Mother Sea',
|
||||
'The Storm', 'The Flood'),
|
||||
|
||||
# 49: The Mould of Man → Effulgent Mould of Man (levity) / Devouring Eagle (gravity)
|
||||
('the-mould-of-man', 49, 'The Effulgent Mould of Man / The Devouring Eagle',
|
||||
'effulgent-mould-devouring-eagle', '',
|
||||
'Trumpets', '',
|
||||
'', '',
|
||||
'The Effulgent Mould of Man', 'The Devouring Eagle',
|
||||
'', ''),
|
||||
]
|
||||
|
||||
_DELETE_SLUGS = [
|
||||
'wheel-of-fortune-em', # old #10 — correspondence absorbed by Fantasia Celestia
|
||||
'the-junkboat', # old #11 — Space element takes the Chariot correspondence
|
||||
'the-great-hunt', # old #14 — Disco Inferno takes the Devil correspondence
|
||||
]
|
||||
|
||||
|
||||
def reseed_earthman_majors(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 # no-op in fresh DB without seeded variants
|
||||
|
||||
# 1. Delete retired cards
|
||||
TarotCard.objects.filter(deck_variant=earthman, slug__in=_DELETE_SLUGS).delete()
|
||||
|
||||
# 2. Update existing cards — set new number to a temporary negative to
|
||||
# avoid any incidental ordering conflicts mid-loop, then finalise.
|
||||
# (No unique constraint on number, so straightforward.)
|
||||
for row in _UPDATES:
|
||||
(cur_slug, new_num, new_name, new_slug, new_group,
|
||||
corr, reversal, lq, gq, le, ge, lr, gr) = row
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, slug=cur_slug,
|
||||
).update(
|
||||
number=new_num,
|
||||
name=new_name,
|
||||
slug=new_slug,
|
||||
group=new_group,
|
||||
correspondence=corr,
|
||||
reversal=reversal,
|
||||
levity_qualifier=lq,
|
||||
gravity_qualifier=gq,
|
||||
levity_emanation=le,
|
||||
gravity_emanation=ge,
|
||||
levity_reversal=lr,
|
||||
gravity_reversal=gr,
|
||||
)
|
||||
|
||||
# 3. Insert The Asteroid Belt (new card, no existing equivalent)
|
||||
TarotCard.objects.get_or_create(
|
||||
deck_variant=earthman,
|
||||
slug='the-asteroid-belt',
|
||||
defaults=dict(
|
||||
number=41,
|
||||
name='The Asteroid Belt',
|
||||
arcana='MAJOR',
|
||||
group='Planets',
|
||||
correspondence='',
|
||||
reversal='Ouroboros',
|
||||
levity_qualifier='Prograde',
|
||||
gravity_qualifier='Retrograde',
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def reverse_reseed(apps, schema_editor):
|
||||
pass # irreversible structural change
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0035_earthman_deck_new_fields'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(reseed_earthman_majors, reverse_reseed),
|
||||
]
|
||||
@@ -1,24 +0,0 @@
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def set_polestar_qualifiers(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, slug='the-polestar',
|
||||
).update(levity_qualifier='Precessional', gravity_qualifier='Recessional')
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0036_earthman_deck_reseed'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(set_polestar_qualifiers, migrations.RunPython.noop),
|
||||
]
|
||||
@@ -1,60 +0,0 @@
|
||||
"""
|
||||
Fix TarotCard.correspondence values for Earthman major arcana to store
|
||||
the Fiorentine/Tarot card name (1:1 correspondence) rather than Earthman
|
||||
conceptual terms.
|
||||
|
||||
Two batches corrected:
|
||||
1. Pope/Horseman (1-5): Territoriality/Despotism/Capitalism/Fascism
|
||||
→ Magician/High Priestess/Empress/Emperor/Hierophant
|
||||
2. Zodiac (22-33): House of Self/Worth/… → Aries/Taurus/…/Pisces
|
||||
(Minchiate Fiorentine has all 12 zodiac sign cards; correspondence = sign name)
|
||||
"""
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
_POPE_FIXES = {
|
||||
'the-schizo': 'Magician',
|
||||
'the-occultist': 'High Priestess',
|
||||
'the-despot': 'Empress',
|
||||
'the-capitalist': 'Emperor',
|
||||
'the-fascist': 'Hierophant',
|
||||
}
|
||||
|
||||
_ZODIAC_FIXES = {
|
||||
'aries': 'Aries',
|
||||
'taurus': 'Taurus',
|
||||
'gemini': 'Gemini',
|
||||
'cancer': 'Cancer',
|
||||
'leo': 'Leo',
|
||||
'virgo': 'Virgo',
|
||||
'libra': 'Libra',
|
||||
'scorpio': 'Scorpio',
|
||||
'sagittarius': 'Sagittarius',
|
||||
'capricorn': 'Capricorn',
|
||||
'aquarius': 'Aquarius',
|
||||
'pisces': 'Pisces',
|
||||
}
|
||||
|
||||
|
||||
def fix_correspondences(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
|
||||
for slug, corr in {**_POPE_FIXES, **_ZODIAC_FIXES}.items():
|
||||
TarotCard.objects.filter(deck_variant=earthman, slug=slug).update(
|
||||
correspondence=corr,
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0037_polestar_qualifiers'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(fix_correspondences, migrations.RunPython.noop),
|
||||
]
|
||||
@@ -1,59 +0,0 @@
|
||||
"""
|
||||
Fix TarotCard.reversal values for Pope/Horseman and Zodiac cards.
|
||||
|
||||
Pope/Horseman (1-5): reversed-state names read from image reversal column.
|
||||
⚠ Cards 1-2 (Schizo/Occultist): image showed 'Territoriality*' spanning
|
||||
rows 1-2 — stored as 'Territoriality' for both; user to confirm if
|
||||
they have distinct reversed names.
|
||||
|
||||
Zodiac (22-33): reversed state = corresponding house (e.g. Aries → House of Self).
|
||||
"""
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
_POPE_REVERSALS = {
|
||||
'the-schizo': 'Territoriality', # ⚠ confirm if distinct from Occultist
|
||||
'the-occultist': 'Territoriality', # ⚠ confirm
|
||||
'the-despot': 'Despotism',
|
||||
'the-capitalist': 'Capitalism',
|
||||
'the-fascist': 'Fascism',
|
||||
}
|
||||
|
||||
_ZODIAC_REVERSALS = {
|
||||
'aries': 'House of Self',
|
||||
'taurus': 'House of Worth',
|
||||
'gemini': 'House of Education',
|
||||
'cancer': 'House of Family',
|
||||
'leo': 'House of Creation',
|
||||
'virgo': 'House of Ritual',
|
||||
'libra': 'House of Cooperation',
|
||||
'scorpio': 'House of Regeneration',
|
||||
'sagittarius': 'House of Enterprise',
|
||||
'capricorn': 'House of Career',
|
||||
'aquarius': 'House of Reward',
|
||||
'pisces': 'House of Reprisal',
|
||||
}
|
||||
|
||||
|
||||
def fix_reversals(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
|
||||
for slug, reversal in {**_POPE_REVERSALS, **_ZODIAC_REVERSALS}.items():
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, slug=slug,
|
||||
).update(reversal=reversal)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0038_fix_correspondences'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(fix_reversals, migrations.RunPython.noop),
|
||||
]
|
||||
@@ -1,24 +0,0 @@
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def rename_jovent_to_intent(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, slug='jovent',
|
||||
).update(name='Intent', slug='intent')
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('epic', '0039_fix_reversals'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(rename_jovent_to_intent, migrations.RunPython.noop),
|
||||
]
|
||||
@@ -1,31 +0,0 @@
|
||||
"""
|
||||
Data migration: delete 4 stray Earthman court cards that were never cleaned up.
|
||||
|
||||
Maid/Jack/Queen/King of Pentacles (suit=PENTACLES, arcana=MINOR, numbers 11-14)
|
||||
are duplicates of the correct Maid/Jack/Queen/King of Crowns (suit=CROWNS,
|
||||
arcana=MIDDLE) that already exist. The PENTACLES rows appeared before migration
|
||||
0024 could catch them and were never removed.
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def delete_stray_pentacles(apps, schema_editor):
|
||||
TarotCard = apps.get_model("epic", "TarotCard")
|
||||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||||
earthman = DeckVariant.objects.filter(slug="earthman").first()
|
||||
if not earthman:
|
||||
return
|
||||
TarotCard.objects.filter(
|
||||
deck_variant=earthman, suit="PENTACLES", number__in=[11, 12, 13, 14],
|
||||
).delete()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("epic", "0040_rename_jovent_to_intent"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(delete_stray_pentacles, migrations.RunPython.noop),
|
||||
]
|
||||
Reference in New Issue
Block a user