You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
4.3 KiB
93 lines
4.3 KiB
import random
|
|
from django.core.management.base import BaseCommand
|
|
from django.db import transaction
|
|
# REPLACE 'your_app' with your actual app name
|
|
from apps.hadis.models import Hadis, Transmitters, NarratorLayer, HadisTransmitter
|
|
|
|
class Command(BaseCommand):
|
|
help = 'Seeds HadisTransmitters: Multiple layers per Hadis, each with an independent chain of 5+ transmitters.'
|
|
|
|
def handle(self, *args, **options):
|
|
self.stdout.write("Starting Global HadisTransmitter seeding (Layer-based Parallel Chains)...")
|
|
|
|
# 1. Fetch Objects
|
|
layers = list(NarratorLayer.objects.all())
|
|
transmitters = list(Transmitters.objects.all())
|
|
hadis_qs = Hadis.objects.all()
|
|
|
|
# 2. Critical Validation
|
|
# We need enough pool size. Minimum requirement: 2 layers * 5 transmitters = 10 unique people.
|
|
if len(layers) < 2:
|
|
self.stdout.write(self.style.ERROR(f"Error: Need at least 2 NarratorLayers, found {len(layers)}."))
|
|
return
|
|
|
|
# If you haven't run the transmitter seeder yet, this might fail.
|
|
if len(transmitters) < 10:
|
|
self.stdout.write(self.style.ERROR(
|
|
f"Error: Found only {len(transmitters)} transmitters. "
|
|
"To satisfy '2 layers x 5 transmitters', you need at least 10 unique transmitters. "
|
|
"Please run the transmitter seeder command first."
|
|
))
|
|
return
|
|
|
|
if not hadis_qs.exists():
|
|
self.stdout.write(self.style.ERROR("No Hadis found."))
|
|
return
|
|
|
|
total_hadis = hadis_qs.count()
|
|
self.stdout.write(f"Found {len(layers)} Layers, {len(transmitters)} Transmitters. Processing {total_hadis} Hadiths...")
|
|
|
|
# 3. Processing
|
|
created_links_count = 0
|
|
|
|
for i, hadis in enumerate(hadis_qs, 1):
|
|
if i % 50 == 0:
|
|
self.stdout.write(f"Processing {i}/{total_hadis}...")
|
|
|
|
with transaction.atomic():
|
|
# A. Wipe existing connections for a clean slate
|
|
HadisTransmitter.objects.filter(hadis=hadis).delete()
|
|
|
|
# B. Determine Structure
|
|
# Constraint: At least 2-3 layers
|
|
num_layers_to_use = random.randint(2, 3)
|
|
|
|
# Don't try to use more layers than exist in DB
|
|
num_layers_to_use = min(num_layers_to_use, len(layers))
|
|
selected_layers = random.sample(layers, num_layers_to_use)
|
|
|
|
# Constraint: At least 5 transmitters per layer (let's say 5 to 7)
|
|
# We calculate total needed first to ensure we pick UNIQUE people for this specific Hadith
|
|
counts_per_layer = [random.randint(5, 7) for _ in range(num_layers_to_use)]
|
|
total_needed = sum(counts_per_layer)
|
|
|
|
# Safety: Ensure we don't ask for more than we have in the whole DB
|
|
if total_needed > len(transmitters):
|
|
self.stdout.write(self.style.WARNING(f"Hadis {hadis.id}: Not enough total transmitters for {num_layers_to_use} layers. Skipping."))
|
|
continue
|
|
|
|
# C. Select Transmitters
|
|
# We pick a unique pool for this Hadith so the same person isn't in 2 layers
|
|
pool = random.sample(transmitters, total_needed)
|
|
|
|
# D. Distribute and Create
|
|
cursor = 0
|
|
for layer_idx, layer in enumerate(selected_layers):
|
|
count = counts_per_layer[layer_idx]
|
|
|
|
# Slice the pool for this layer
|
|
layer_group = pool[cursor : cursor + count]
|
|
cursor += count
|
|
|
|
# Create Links with Independent Ordering (0, 1, 2...) for THIS layer
|
|
for order_index, transmitter in enumerate(layer_group):
|
|
HadisTransmitter.objects.create(
|
|
hadis=hadis,
|
|
transmitter=transmitter,
|
|
narrator_layer=layer,
|
|
order=order_index, # Resets to 0 for every layer!
|
|
status=transmitter.reliability if hasattr(transmitter, 'reliability') else None
|
|
)
|
|
created_links_count += 1
|
|
|
|
self.stdout.write(self.style.SUCCESS(f"Done! Created {created_links_count} connections."))
|