import mongoose from 'mongoose'; import Series from '../server/models/series.js'; import Event from '../server/models/event.js'; const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/ghostguild'; async function addCoopValuesSeries() { try { // Connect to MongoDB await mongoose.connect(MONGODB_URI); console.log('Connected to MongoDB'); // Create the series const seriesData = { id: 'coop-values-into-practice-2025', title: 'Cooperative Values into Practice', description: 'A practical, region-agnostic foundation in cooperative values and governance for game studio founders interested in worker-centric, anti-capitalist models. Structured as a peer-driven workshop emphasizing reciprocal learning and sharing.', type: 'workshop_series', isVisible: true, isActive: true, targetCircles: ['founder', 'practitioner'], totalEvents: 6, createdBy: 'admin@ghostguild.org', tickets: { enabled: true, requiresSeriesTicket: false, allowIndividualEventTickets: true, currency: 'CAD', member: { available: true, isFree: true, price: 0, name: 'Member Series Pass', description: 'Free access to all sessions in the Cooperative Values into Practice series for Ghost Guild members.' }, public: { available: true, name: 'Series Pass', description: 'Access to all 6 sessions in the Cooperative Values into Practice series', price: 150, quantity: 20 }, capacity: { total: 30 }, waitlist: { enabled: true, maxSize: 15 } } }; // Check if series already exists let series = await Series.findOne({ id: seriesData.id }); if (series) { console.log('Series already exists, updating...'); series = await Series.findOneAndUpdate( { id: seriesData.id }, seriesData, { new: true, runValidators: true } ); } else { console.log('Creating new series...'); series = new Series(seriesData); await series.save(); } console.log('Series created/updated:', series.title); // Base date for scheduling (adjust as needed) const baseDate = new Date('2025-11-01T18:00:00.000Z'); // Starting November 1, 2025, 6 PM UTC // Create the events const eventsData = [ { title: 'Module 0: Orientation', tagline: 'Welcome to Cooperative Values into Practice', description: 'Introduce the goals and format of the program, quick power & identity reflections, Baby Ghosts values, and create group agreements.', content: `## Welcome! This orientation session kicks off our 6-month journey exploring cooperative values and governance for game studios. ## What We'll Cover - Program goals and format - Power & identity reflections - Baby Ghosts values introduction - Creating our group agreements together ## Homework Power Flower exercise to complete before Module 1 ## Who Should Attend This series is designed for: - Game studio founders interested in worker-centric models - Practitioners exploring cooperative structures - Anyone committed to anti-capitalist, democratic workplaces`, position: 0, weeks: 0 }, { title: 'Module 1: Principles', tagline: 'Understanding cooperative foundations', description: 'Explore the difference between coops and traditional studios, foundational cooperative principles, historical and cultural context, and how they challenge industry norms.', content: `## Cooperative Principles Understanding what makes cooperatives different from traditional game studios. ## Topics - Coops vs. traditional studios - key differences - Foundational cooperative principles - How cooperative values challenge industry norms - Historical and cultural context - Introduction to Coops for Creatives ## Activities - Values Reflection exercise - Value Mapping workshop ## Between Sessions Reflect on how cooperative principles align with your studio vision.`, position: 1, weeks: 3 }, { title: 'Module 2: Purpose', tagline: 'Alignment, agreement, and shared vision', description: 'Learn the difference between alignment, agreement, and false consensus. Reflect on cooperative origin stories, discuss financial needs and capacity, and map collective visions.', content: `## Finding Your Cooperative Purpose Moving beyond false consensus to genuine alignment. ## Topics - The difference between alignment, agreement, and false consensus - Reflecting on cooperative origin stories and values - Discussing financial needs, availability, and capacity - Mapping collective visions for scale and pace - Clarifying roles, expectations, and contribution levels ## Activities - Origin Stories sharing - Solidarity Press exercise - "The Talk" - discussing money and capacity - Scale & Pace Alignment worksheets ## Between Sessions Continue conversations about purpose and alignment with your team.`, position: 2, weeks: 4 }, { title: 'Module 3: Practices Part 1 - Meetings & Decision-Making', tagline: 'Democratic processes in action', description: 'Move from boss-decides or majority-rules to cooperative approaches. Learn to redesign hierarchical meetings and facilitate inclusive, productive discussions.', content: `## Democratic Practices: Meetings Redesigning how we make decisions together. ## Topics - Moving from boss-decides or majority-rules to cooperative approaches - Redesigning hierarchical meetings - Tips for facilitating inclusive, productive meetings - Consensus-building techniques - Managing power dynamics in meetings ## Activities - Meeting redesign workshop - Facilitation practice - Decision-making simulations ## Between Sessions Try implementing new meeting practices with your team.`, position: 3, weeks: 4 }, { title: 'Module 4: Practices Part 2 - Finances & Governance', tagline: 'Transparent systems for cooperative work', description: 'Design transparent financial practices and systems, reframe disagreement as valuable information, and establish clear governance structures.', content: `## Democratic Practices: Money & Structure Building transparent financial and governance systems. ## Topics - Designing transparent financial practices and systems - Open book management for cooperatives - Reframing disagreement from failure to valuable information - Establishing clear governance systems - Creating accountability without hierarchy ## Activities - Financial transparency workshop - Governance structure design - Conflict as data reframing ## Between Sessions Draft governance documents or financial transparency practices for your studio.`, position: 4, weeks: 4 }, { title: 'Module 5: Pathways Forward', tagline: 'Your cooperative journey continues', description: 'Integrate learnings, share next steps, create accountability partnerships, and celebrate the work done together.', content: `## Moving Forward Together Bringing it all together and planning your next steps. ## Topics - Integrating everything we've learned - Individual and collective action plans - Creating accountability partnerships - Resources for ongoing learning - Building a community of practice ## Activities - Action planning workshop - Accountability partner matching - Celebration and reflection ## What's Next Continue your cooperative journey with Ghost Guild support and your cohort connections.`, position: 5, weeks: 4 } ]; let currentDate = new Date(baseDate); const createdEvents = []; for (const eventData of eventsData) { // Calculate dates const startDate = new Date(currentDate); const endDate = new Date(startDate); endDate.setHours(endDate.getHours() + 2); // 2-hour sessions const eventPayload = { title: eventData.title, tagline: eventData.tagline, description: eventData.description, content: eventData.content, startDate, endDate, eventType: 'workshop', location: '#ghost-guild-workshops', // Slack channel isOnline: true, isVisible: true, membersOnly: false, series: { id: series.id, title: series.title, description: series.description, type: series.type, position: eventData.position + 1, // 1-indexed for display totalEvents: 6, isSeriesEvent: true }, tickets: { enabled: true, requiresSeriesTicket: false, seriesTicketReference: series._id, currency: 'CAD', member: { available: true, isFree: true, price: 0, name: 'Member Ticket', description: 'Free for Ghost Guild members' }, public: { available: true, name: 'Single Session Ticket', description: 'Attend this individual session', price: 30, quantity: 10 }, capacity: { total: 30 }, waitlist: { enabled: true, maxSize: 10 } }, targetCircles: ['founder', 'practitioner'], registrationRequired: true, createdBy: 'admin@ghostguild.org' }; // Check if event already exists (by title and series) const existingEvent = await Event.findOne({ title: eventPayload.title, 'series.id': series.id }); let event; if (existingEvent) { console.log(`Updating existing event: ${eventPayload.title}`); event = await Event.findByIdAndUpdate( existingEvent._id, eventPayload, { new: true, runValidators: true } ); } else { console.log(`Creating event: ${eventPayload.title}`); event = new Event(eventPayload); await event.save(); } createdEvents.push(event); // Move to next session date (add weeks) if (eventData.weeks > 0) { currentDate.setDate(currentDate.getDate() + (eventData.weeks * 7)); } } // Update series with date range from events const firstEvent = createdEvents[0]; const lastEvent = createdEvents[createdEvents.length - 1]; series.startDate = firstEvent.startDate; series.endDate = lastEvent.endDate; series.totalEvents = createdEvents.length; await series.save(); console.log('\n✅ Successfully created/updated series and all events!'); console.log(`\nSeries: ${series.title}`); console.log(`Events created: ${createdEvents.length}`); console.log(`Date range: ${series.startDate.toLocaleDateString()} - ${series.endDate.toLocaleDateString()}`); console.log('\nEvents:'); createdEvents.forEach((event, index) => { console.log(` ${index + 1}. ${event.title} - ${event.startDate.toLocaleDateString()}`); }); } catch (error) { console.error('Error:', error); } finally { await mongoose.connection.close(); console.log('\nDatabase connection closed'); } } // Run the script addCoopValuesSeries();