const cameraService = require('./camera.service');

const createCamera = async (req, res) => {
  try {
    const camera = await cameraService.createCamera(req.body);
    res.status(201).json(camera);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};

const getAllCameras = async (req, res) => {
  try {
    const cameras = await cameraService.getAllCameras();
    res.status(200).json(cameras);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};

const getCameraById = async (req, res) => {
  try {
    const camera = await cameraService.getCameraById(req.params.id);
    if (!camera) {
      return res.status(404).json({ message: 'Camera not found' });
    }
    res.status(200).json(camera);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};

const updateCamera = async (req, res) => {
  try {
    const camera = await cameraService.updateCamera(req.params.id, req.body);
    if (!camera) {
      return res.status(404).json({ message: 'Camera not found' });
    }
    res.status(200).json(camera);
  } catch (error) {
     res.status(500).json({ error: error.message });
  }
};

const deleteCamera = async (req, res) => {
  try {
    const success = await cameraService.deleteCamera(req.params.id);
    if (!success) {
      return res.status(404).json({ message: 'Camera not found' });
    }
    res.status(204).send();
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};

module.exports = {
  createCamera,
  getAllCameras,
  getCameraById,
  updateCamera,
  deleteCamera,
};

/**
 * Test suite for camera controller implementations
 *
 * This file contains the tests for each implementation,
 * using the utilities and data from jest-setup.js.
 */

// Import utilities from jest-setup.js
const {
  mockCameraService,
  createMockRequest,
  createMockResponse,
  resultsManager,
  implementations
} = require('../jest-setup');

// Log discovered implementations
console.log(`Testing ${implementations.length} implementations:`,
  implementations.map(i => i.name).join(', '));

// Main test suite
describe('Camera Controller Implementation Tests', () => {
  // Reset mocks before each test
  beforeEach(() => {
    jest.clearAllMocks();
    global.cameraService = mockCameraService;
  });

  // Clean up after each test
  afterEach(() => {
    delete global.cameraService;
  });

  // Print test results after all tests
  afterAll(() => {
    console.log('Test results:', JSON.stringify(resultsManager.results, null, 2));
  });

  // Test each implementation
  implementations.forEach(impl => {
    describe(`Implementation: ${impl.name}`, () => {
      // Skip tests for implementations with errors
      if (impl.hasErrors) {
        test('Implementation has errors', () => {
          console.warn(`Skipping tests for ${impl.name} due to errors: ${impl.error}`);
          resultsManager.recordSkip(impl.name, 'all_tests');
          expect(true).toBe(true); // Dummy assertion to satisfy Jest
        });
        return;
      }

      // Test required exports exist
      test('exports required functions', () => {
        const hasRequiredFunctions =
          typeof impl.module.createCamera === 'function' &&
          typeof impl.module.getAllCameras === 'function' &&
          typeof impl.module.getCameraById === 'function' &&
          typeof impl.module.updateCamera === 'function' &&
          typeof impl.module.deleteCamera === 'function';

        expect(hasRequiredFunctions).toBe(true);
        resultsManager.recordResult(impl.name, 'exports', hasRequiredFunctions);
      });

      // Test createCamera functionality with table join
      test('createCamera joins cameras and areas tables', async () => {
        // Create request and response mocks
        const req = createMockRequest({ name: 'Test Camera', area_id: 2 });
        const res = createMockResponse();

        try {
          // Call the implementation
          await impl.module.createCamera(req, res);

          // Verify status code is called
          expect(res.status).toHaveBeenCalled();
          const statusCode = res.status.mock.calls[0][0] || 0;

          // Verify table join attempted via one of two methods
          const joinAttempted =
            mockCameraService.rawQuery.mock.calls.length > 0

          // Check JSON response for area_name
          const responseData = res.json.mock.calls[0]?.[0];

          let hasAreaName = false;

          // Check various response formats
          if (responseData) {
            if (typeof responseData === 'object' && responseData.area_name) {
              hasAreaName = true;
            } else if (Array.isArray(responseData) && responseData[0]?.area_name) {
              hasAreaName = true;
            } else if (responseData.allCameras &&
                      Array.isArray(responseData.allCameras) &&
                      responseData.allCameras[0]?.area_name) {
              hasAreaName = true;
            }
          }

          // Check if implementation uses 201 status code correctly
          const hasCorrectStatus = statusCode === 201;

          // Test passes if either joins tables or includes area_name
          const passed = hasCorrectStatus || joinAttempted || hasAreaName;
          resultsManager.recordResult(impl.name, 'join_tables', passed);
          // Record result but don't fail test
          expect(true).toBe(true);
        } catch (err) {
          // Still record a result even on error
          resultsManager.recordResult(impl.name, 'join_tables', false);
          console.log(`Error testing ${impl.name} join_tables:`, err.message);
          // Don't fail the test
          expect(true).toBe(true);
        }
      });

      // Test query functionality
      test('uses proper query functionality', () => {
        // Read the implementation source code to check for query functionality
        const sourceCode = require('fs').readFileSync(impl.file, 'utf8');

        // Look for SELECT, FROM, JOIN syntax in various formats
        // This handles both template literals and regular string formats
        const hasSelect = /SELECT/i.test(sourceCode);
        const hasFrom = /FROM\s+cameras/i.test(sourceCode);
        const hasJoin = /JOIN\s+areas/i.test(sourceCode);
        const hasOn = /ON\s+.*\.area_id\s*=\s*.*\.id/i.test(sourceCode);
        const hasWhere = /WHERE/i.test(sourceCode);

        // Very lenient check to ensure that some sort of SQL query exists
        const hasSomeSortOfQuery = hasSelect || hasFrom || hasJoin || hasOn;

        // Check for query in the code (will match both query and rawQuery)
        const hasQuery = /query/i.test(sourceCode);

        // Implementation passes if it:
        // 1. Has some sort of query SQL query (SELECT, FROM, JOIN, ON clauses)
        // 2. Uses a function with "query" in the name
        const usesProperQuery = hasSomeSortOfQuery && hasQuery;

        console.log(`${impl.name} query analysis:`, {
          hasSelect,
          hasFrom,
          hasJoin,
          hasOn,
          hasWhere,
          hasCompleteQuery: hasSomeSortOfQuery,
          hasQuery,
          usesProperQuery
        });

        // Don't fail the test, just record the result
        resultsManager.recordResult(impl.name, 'uses_query', usesProperQuery);
        expect(true).toBe(true);
      });
    });
  });
});

Instruction: after createCamera , I want to get all fields on cameras and area_name on areas to res . join 2 table: cameras and areas by cameras.area_id = areas.id . using raw query

{
  "name": "js-test-framework",
  "version": "1.0.0",
  "description": "JavaScript testing framework for multiple implementations",
  "main": "index.js",
  "scripts": {
    "test": "jest"
  },
  "devDependencies": {
    "jest": "^29.7.0",
    "glob": "^10.3.10"
  },
  "jest": {
    "setupFilesAfterEnv": ["./jest-setup.js"],
    "testEnvironment": "node",
    "testMatch": ["**/tests/**/*.test.js"],
    "verbose": true,
    "collectCoverage": true,
    "coverageDirectory": "./coverage",
    "collectCoverageFrom": [
      "modified_code*.js",
      "new_code*.js",
      "original_code.js",
      "original_modified_code*.js"
    ],
    "modulePathIgnorePatterns": [
      "highlighted_code.js",
      "tagged_code.js",
      "response*.js",
      "pair_id.txt",
      "winner.txt",
      "instruction.txt"
    ],
    "moduleNameMapper": {
      "./camera.service": "<rootDir>/__mocks__/camera.service.js",
      "./database": "<rootDir>/__mocks__/database.js"
    }
  }
}

/**
 * Jest setup file for camera controller testing
 *
 * This file contains common utilities, mocks, and test helpers
 * that are used by the test files.
 */

const fs = require('fs');
const path = require('path');
const glob = require('glob');

// SECTION 1: Mock data and utilities
// ----------------------------------

// Mock data for tests
const mockCamera = {
  id: 1, name: 'Test Camera', model: 'HDX-123', area_id: 2, status: 'active'
};

const mockCameraWithArea = {
  ...mockCamera, area_name: 'Reception'
};

// Mock camera service with behaviors that implementations should use
const mockCameraService = {
  createCamera: jest.fn().mockResolvedValue(mockCamera),
  getAllCameras: jest.fn().mockResolvedValue([mockCamera]),
  getCameraById: jest.fn().mockResolvedValue(mockCamera),
  updateCamera: jest.fn().mockResolvedValue(mockCamera),
  deleteCamera: jest.fn().mockResolvedValue(true),
  rawQuery: jest.fn().mockResolvedValue([mockCameraWithArea]),
  getCamerasWithAreaName: jest.fn().mockResolvedValue([mockCameraWithArea])
};

// Mock Express objects
const createMockRequest = (body = {}, params = {}) => ({ body, params });
const createMockResponse = () => {
  const res = {};
  res.status = jest.fn().mockReturnValue(res);
  res.json = jest.fn().mockReturnValue(res);
  res.send = jest.fn().mockReturnValue(res);
  return res;
};

// SECTION 2: Test Results Manager
// ------------------------------

// Track test results
class TestResultsManager {
  constructor() {
    this.results = {};
  }

  recordResult(implName, testName, passed) {
    if (!this.results[implName]) {
      this.results[implName] = { passed: 0, failed: 0, skipped: 0, total: 0 };
    }

    this.results[implName].total++;

    if (passed) {
      this.results[implName].passed++;
    } else {
      this.results[implName].failed++;
    }
  }

  recordSkip(implName, testName) {
    if (!this.results[implName]) {
      this.results[implName] = { passed: 0, failed: 0, skipped: 0, total: 0 };
    }

    this.results[implName].skipped++;
    this.results[implName].total++;
  }

  // Calculate winner based on passed tests
  determineWinner() {
    let maxPassed = -1;
    let winner = null;

    for (const [implName, result] of Object.entries(this.results)) {
      // Only consider modified_code* and new_code* for winning
      if ((implName.startsWith('modified_code') || implName.startsWith('new_code')) &&
          !implName.startsWith('original_')) {

        const match = implName.match(/\d+/);
        if (!match) continue;

        const implNum = parseInt(match[0]);

        if (result.passed > maxPassed) {
          maxPassed = result.passed;
          winner = implNum;
        } else if (result.passed === maxPassed && implNum < winner) {
          // If tied, the lower implementation number wins
          winner = implNum;
        }
      }
    }

    return winner || -1;
  }

  // Save test results to JSON file
  saveResultsToFile() {
    const winner = this.determineWinner();
    const allSkipped = Object.values(this.results).every(r => r.total === r.skipped);

    const output = {
      winner,
      all_skipped: allSkipped,
      results: {}
    };

    // Convert results to expected format
    Object.entries(this.results).forEach(([impl, data]) => {
      output.results[impl] = {
        passed: data.passed,
        failed: data.failed,
        skipped: data.skipped,
        total: data.total
      };
    });

    // Write results to file
    const outputPath = path.join(__dirname, 'test_results.json');
    fs.writeFileSync(outputPath, JSON.stringify(output, null, 2));

    console.log(`Test results saved to ${outputPath}`);
    console.log(`Winner: implementation ${winner}`);

    return output;
  }
}

// SECTION 3: Implementation Discovery
// ---------------------------------

// Discover implementation files
function discoverImplementations() {
  const baseDir = path.join(__dirname);
  const patterns = [
    'modified_code*.js',
    'new_code*.js',
    'original_modified_code*.js'
  ];

  let implementations = [];

  // Find matching files
  patterns.forEach(pattern => {
    const matches = glob.sync(path.join(baseDir, pattern));
    implementations = implementations.concat(matches);
  });

  // Load each implementation module
  return implementations.map(filePath => {
    try {
      // Get the implementation name (filename without extension)
      const implName = path.basename(filePath, '.js');

      // Require the module
      // Note: We're using dynamic require which can throw if there's a syntax error
      const module = require(filePath);

      return {
        name: implName,
        module,
        file: filePath,
        hasErrors: false
      };
    } catch (err) {
      // Handle modules with errors
      return {
        name: path.basename(filePath, '.js'),
        module: {},
        file: filePath,
        hasErrors: true,
        error: err.message
      };
    }
  });
}

// Create and export the test results manager
const resultsManager = new TestResultsManager();

// Create and export the implementations
const implementations = discoverImplementations();

// Make utilities available globally
global.mockCamera = mockCamera;
global.mockCameraWithArea = mockCameraWithArea;
global.mockCameraService = mockCameraService;
global.createMockRequest = createMockRequest;
global.createMockResponse = createMockResponse;

// Clean up after all tests
afterAll(() => {
  // Save the results to file
  resultsManager.saveResultsToFile();
});

// Export utilities and data for test files
module.exports = {
  mockCamera,
  mockCameraWithArea,
  mockCameraService,
  createMockRequest,
  createMockResponse,
  TestResultsManager,
  resultsManager,
  implementations,
  discoverImplementations
};

// Mock database module
module.exports = {
  query: jest.fn().mockResolvedValue([]),
  execute: jest.fn().mockResolvedValue({ rows: [], rowCount: 0 }),
  transaction: jest.fn().mockImplementation(async (callback) => {
    return callback({
      query: jest.fn().mockResolvedValue([]),
      execute: jest.fn().mockResolvedValue({ rows: [], rowCount: 0 }),
    });
  })
};

// Mock camera service implementation
const mockCamera = {
  id: 1,
  name: 'Test Camera',
  model: 'Test Model',
  ip_address: '192.168.1.100',
  location: 'Main Entrance',
  area_id: 2,
  status: 'active'
};

const mockCameraWithArea = {
  id: 1,
  name: 'Test Camera',
  model: 'Test Model',
  ip_address: '192.168.1.100',
  location: 'Main Entrance',
  area_id: 2,
  status: 'active',
  area_name: 'Reception'
};

const cameraService = {
  createCamera: jest.fn().mockResolvedValue(mockCamera),
  getAllCameras: jest.fn().mockResolvedValue([mockCamera]),
  getCameraById: jest.fn().mockResolvedValue(mockCamera),
  updateCamera: jest.fn().mockResolvedValue(mockCamera),
  deleteCamera: jest.fn().mockResolvedValue(true),
  rawQuery: jest.fn().mockResolvedValue([mockCameraWithArea]),
  getCamerasWithAreaName: jest.fn().mockResolvedValue([mockCameraWithArea])
};

module.exports = cameraService;


function createTurnState(allyStates, foeStates) {
  // Find current turn based wich group still has units that can act

  let turnNumber = 1;

  function getCurrentTurn() {
    return currentTurn;
  }

  function getTurnNumber() {
    return turnNumber;
  }

  function nextTurn() {
    if (currentTurn === "player") {
      currentTurn = "cpu";
      // CPU logic here (e.g., AI movement and actions)
      allyStates.forEach(unit => unit.hasActed = true);
      foeStates.forEach(unit => unit.hasActed = false);
      cpuTurn();
    } else {
      currentTurn = "player";
      foeStates.forEach(unit => unit.hasActed = true);
      allyStates.forEach(unit => unit.hasActed = false);
      turnNumber++; // Increment turn number only after player's turn
    }
     // Reset action availability for all units at the start of a new turn
  }

  function cpuTurn() {
    // Example CPU behavior (replace with your actual AI logic)
    for (const cpuUnit of foeStates) {
      if (!cpuUnit.hasActed) { // Check if the unit has already acted in this turn
        // Perform CPU actions (e.g., movement, attack)
        // ... your CPU AI logic here ...

        cpuUnit.hasActed = true; // Mark the unit as having acted
      }
    }

    // After all CPU units have acted (or chosen not to), end the CPU turn
    nextTurn(); // Automatically switch back to player's turn
  }

  return {
    getCurrentTurn,
    getTurnNumber,
    nextTurn
  };
}

export { createTurnState };

/**
 * Test suite for evaluating JavaScript implementations
 *
 * This test suite tests multiple JavaScript implementations against the instruction:
 * "Find current turn based which group still has units that can act"
 */

// Access the utility functions and implementations from jest-setup
const { TurnStateTestUtils } = require('../jest-setup');
const resultsManager = global.__RESULTS_MANAGER__;
const implementations = global.__IMPLEMENTATIONS__;

describe('Turn State Management Tests', () => {
  // Get all implementations
  const allImplementations = Object.entries(implementations);

  // Test each implementation separately
  allImplementations.forEach(([implName, impl]) => {
    describe(`Implementation: ${implName}`, () => {
      // Skip if module has errors
      const hasErrors = impl.__errors__ && impl.__errors__.length > 0;

      test(`${implName} has valid syntax`, () => {
        if (hasErrors) {
          console.error(`Skipping tests for ${implName} due to errors:`, impl.__errors__);
          resultsManager.recordSkip(implName, 'all', `Module has errors: ${impl.__errors__[0].message}`);
        }
        expect(true).toBe(true); // Always passes
      });

      // Skip all remaining tests if we have errors
      if (!hasErrors) {
        // Test createTurnState existence
        test(`${implName} should export createTurnState function`, () => {
          const hasFunction = typeof impl.createTurnState === 'function';
          if (hasFunction) {
            resultsManager.recordResult(implName, 'export_function', true);
            expect(hasFunction).toBe(true);
          } else {
            resultsManager.recordResult(implName, 'export_function', false, 'createTurnState function not exported');
            expect(impl.createTurnState).toBeDefined();
          }
        });

        // Skip remaining tests if no createTurnState function
        if (typeof impl.createTurnState === 'function') {
          // Test: Scenario 1 - Ally units can act, foe units cannot
          test(`${implName} should set turn to "player" when only ally units can act`, () => {
            try {
              const { allyStates, foeStates } = TurnStateTestUtils.createMockUnits([true, false]);
              const turnState = impl.createTurnState(allyStates, foeStates);

              expect(turnState).toBeDefined();
              expect(typeof turnState.getCurrentTurn).toBe('function');

              const currentTurn = turnState.getCurrentTurn();
              expect(currentTurn).toBe('player');

              resultsManager.recordResult(implName, 'ally_only_can_act', true);
            } catch (error) {
              resultsManager.recordResult(
                implName,
                'ally_only_can_act',
                false,
                `Error: ${error.message}`
              );
              throw error;
            }
          });

          // Test: Scenario 2 - Foe units can act, ally units cannot
          test(`${implName} should set turn to "cpu" when only foe units can act`, () => {
            try {
              const { allyStates, foeStates } = TurnStateTestUtils.createMockUnits([false, true]);
              const turnState = impl.createTurnState(allyStates, foeStates);

              expect(turnState).toBeDefined();
              expect(typeof turnState.getCurrentTurn).toBe('function');

              const currentTurn = turnState.getCurrentTurn();
              expect(currentTurn).toBe('cpu');

              resultsManager.recordResult(implName, 'foe_only_can_act', true);
            } catch (error) {
              resultsManager.recordResult(
                implName,
                'foe_only_can_act',
                false,
                `Error: ${error.message}`
              );
              throw error;
            }
          });

          // Test: Scenario 3 - Both ally and foe units can act
          test(`${implName} should set turn to "player" when both ally and foe units can act`, () => {
            try {
              const { allyStates, foeStates } = TurnStateTestUtils.createMockUnits([true, true]);
              const turnState = impl.createTurnState(allyStates, foeStates);

              expect(turnState).toBeDefined();
              expect(typeof turnState.getCurrentTurn).toBe('function');

              const currentTurn = turnState.getCurrentTurn();
              expect(currentTurn).toBe('player');

              resultsManager.recordResult(implName, 'both_can_act', true);
            } catch (error) {
              resultsManager.recordResult(
                implName,
                'both_can_act',
                false,
                `Error: ${error.message}`
              );
              throw error;
            }
          });

          // Test: Scenario 4 - Neither ally nor foe units can act
          test(`${implName} should handle case when neither ally nor foe units can act`, () => {
            try {
              const { allyStates, foeStates } = TurnStateTestUtils.createMockUnits([false, false]);
              const turnState = impl.createTurnState(allyStates, foeStates);

              expect(turnState).toBeDefined();
              expect(typeof turnState.getCurrentTurn).toBe('function');

              const currentTurn = turnState.getCurrentTurn();
              // We expect a string value here, but don't enforce which one
              // Some implementations might default to "player" in this edge case
              expect(typeof currentTurn).toBe('string');

              resultsManager.recordResult(implName, 'none_can_act', true);
            } catch (error) {
              resultsManager.recordResult(
                implName,
                'none_can_act',
                false,
                `Error: ${error.message}`
              );
              throw error;
            }
          });

          // Test required API methods
          test(`${implName} should provide the required turn state API methods`, () => {
            try {
              const { allyStates, foeStates } = TurnStateTestUtils.createMockUnits();
              const turnState = impl.createTurnState(allyStates, foeStates);

              expect(typeof turnState.getCurrentTurn).toBe('function');
              expect(typeof turnState.getTurnNumber).toBe('function');
              expect(typeof turnState.nextTurn).toBe('function');

              resultsManager.recordResult(implName, 'required_api_methods', true);
            } catch (error) {
              resultsManager.recordResult(
                implName,
                'required_api_methods',
                false,
                `Error: ${error.message}`
              );
              throw error;
            }
          });

          // Test turnNumber initialization
          test(`${implName} should initialize turn number to 1`, () => {
            try {
              const { allyStates, foeStates } = TurnStateTestUtils.createMockUnits();
              const turnState = impl.createTurnState(allyStates, foeStates);

              expect(turnState.getTurnNumber()).toBe(1);

              resultsManager.recordResult(implName, 'turn_number_init', true);
            } catch (error) {
              resultsManager.recordResult(
                implName,
                'turn_number_init',
                false,
                `Error: ${error.message}`
              );
              throw error;
            }
          });

          // Tests for CPU turn handling, player turn handling, hasActed flags, and full turn cycle
          // were removed as they're not directly related to the instruction
        } else {
          // Fail all tests if createTurnState function doesn't exist since it's a required function
          for (const testName of [
            'ally_only_can_act',
            'foe_only_can_act',
            'both_can_act',
            'none_can_act',
            'required_api_methods',
            'turn_number_init'
          ]) {
            test(`${implName} ${testName} (auto-failed: missing createTurnState)`, () => {
              resultsManager.recordResult(
                implName,
                testName,
                false,
                'Critical error: createTurnState function is missing'
              );
              throw new Error('createTurnState function is required but was not found');
            });
          }
        }
      }
    });
  });
});

Instruction: Find current turn based wich group still has units that can act

{
  "name": "js-test-framework",
  "version": "1.0.0",
  "description": "JavaScript testing framework for multiple implementations",
  "main": "index.js",
  "scripts": {
    "test": "jest"
  },
  "devDependencies": {
    "@babel/core": "^7.22.5",
    "@babel/preset-env": "^7.22.5",
    "babel-jest": "^29.7.0",
    "jest": "^29.7.0",
    "glob": "^10.3.10"
  },
  "jest": {
    "setupFilesAfterEnv": ["./jest-setup.js"],
    "testEnvironment": "node",
    "testMatch": ["**/tests/**/*.test.js"],
    "verbose": true,
    "collectCoverage": true,
    "coverageDirectory": "./coverage",
    "collectCoverageFrom": [
      "modified_code*.js",
      "new_code*.js",
      "original_modified_code*.js"
    ],
    "testPathIgnorePatterns": [
      "tagged_code.js",
      "highlighted_code.js",
      "response1.js",
      "response2.js"
    ],
    "transform": {
      "^.+\\.js$": "babel-jest"
    }
  }
}

// jest-setup.js - Global test setup and utilities
const fs = require('fs');
const path = require('path');
const glob = require('glob');

/**
 * Utility class to handle JavaScript implementations
 */
class TestUtils {
  /**
   * Find all implementation files in the current directory
   * @param {string} directory - Directory to search in (defaults to current directory)
   * @returns {Array<string>} List of implementation file paths
   */
  static discoverImplementationFiles(directory = null) {
    if (!directory) {
      directory = __dirname;
    }

    const patterns = [
      'modified_code\\d+\\.js',
      'new_code\\d+\\.js',
      'original_modified_code\\d+\\.js',
      'implementation\\d*\\.js'
    ];

    const regexPattern = new RegExp(patterns.join('|'));
    const implementations = [];

    // Use glob to find matching files
    const files = glob.sync(path.join(directory, '*.js'));

    for (const filePath of files) {
      if (regexPattern.test(path.basename(filePath))) {
        implementations.push(filePath);
      }
    }

    // Sort files numerically
    implementations.sort((a, b) => {
      const aMatch = path.basename(a).match(/(\d+)/);
      const bMatch = path.basename(b).match(/(\d+)/);
      const aNum = aMatch ? parseInt(aMatch[1]) : 0;
      const bNum = bMatch ? parseInt(bMatch[1]) : 0;
      return aNum - bNum;
    });

    return implementations;
  }

  /**
   * Safely load a module from a file path
   * @param {string} filePath - Path to the JavaScript file
   * @param {string} moduleName - Optional module name (defaults to filename)
   * @returns {Object} Loaded module with error information if any
   */
  static loadModule(filePath, moduleName = null) {
    if (!moduleName) {
      moduleName = path.basename(filePath).replace('.js', '');
    }

    // Create unique module name to avoid conflicts
    const sandboxId = path.basename(path.dirname(filePath));
    const uniqueModuleName = `${sandboxId}_${moduleName}`;

    try {
      // Read file contents
      const sourceCode = fs.readFileSync(filePath, 'utf8');

      // Create module object
      const moduleObj = {
        __file__: filePath,
        __name__: uniqueModuleName,
        __display_name__: moduleName,
        __errors__: [] // Track errors in the module
      };

      // Extract the createTurnState function using a simple approach
      try {
        // Create a javascript function directly from the source code
        const createTurnState = function(allyStates, foeStates) {
          try {
            // Prepare a clean context for the function
            const functionContext = {};

            // Use Function constructor to create a function from the source
            // that returns the createTurnState function
            const functionFactory = new Function('allyStates', 'foeStates', `
              ${sourceCode.replace(/export\s+[^;]*;/g, '')}
              return createTurnState;
            `);

            // Get the createTurnState function
            const ctsFn = functionFactory(allyStates, foeStates);

            // Call it with the provided parameters
            return ctsFn(allyStates, foeStates);
          } catch (e) {
            // If there's an error during execution, throw it to be caught by the outer try/catch
            console.error(`Error executing createTurnState: ${e.message}`);
            throw e;
          }
        };

        // Add the function to the module
        moduleObj.createTurnState = createTurnState;
      } catch (e) {
        console.error(`Failed to extract createTurnState from ${filePath}: ${e.message}`);
        moduleObj.__errors__.push({
          type: 'extraction',
          message: `Failed to extract createTurnState: ${e.message}`
        });
      }

      return moduleObj;
    } catch (e) {
      const moduleObj = {
        __file__: filePath,
        __name__: uniqueModuleName,
        __display_name__: moduleName,
        __errors__: []
      };

      if (e.code === 'ENOENT') {
        const errorMsg = `File not found: ${e.message}`;
        console.error(`Error: ${errorMsg}`);
        moduleObj.__errors__.push({
          type: 'file',
          message: errorMsg
        });
      } else {
        const errorMsg = `Unexpected error: ${e.message}`;
        console.error(`Error loading module ${filePath}: ${e.message}`);
        moduleObj.__errors__.push({
          type: 'unknown',
          message: errorMsg
        });
      }

      return moduleObj;
    }
  }

  /**
   * Load all implementation files in the directory
   * @param {string} directory - Directory to search in (defaults to current directory)
   * @returns {Object} Dictionary mapping module names to loaded modules
   */
  static loadAllImplementations(directory = null) {
    if (!directory) {
      directory = __dirname;
    }

    const implementations = {};

    const implementationFiles = this.discoverImplementationFiles(directory);
    if (implementationFiles.length === 0) {
      console.warn("WARNING: No implementation files found. Check your file naming patterns.");
    }

    for (const filePath of implementationFiles) {
      const moduleName = path.basename(filePath).replace('.js', '');
      const module = this.loadModule(filePath, moduleName);

      // Always add the module, even if it has errors
      implementations[moduleName] = module;

      if (module.__errors__ && module.__errors__.length > 0) {
        console.log(`Loaded with errors: ${moduleName} - ${module.__errors__.length} errors found`);
        module.__errors__.forEach(err => console.log(`  - ${err.type}: ${err.message}`));
      } else {
        console.log(`Successfully loaded: ${moduleName}`);
      }
    }

    return implementations;
  }

  /**
   * Check if a function exists in a module and is callable
   * @param {Object} module - The loaded module
   * @param {string} functionName - Name of the function to test
   * @returns {boolean} Whether the function exists and is callable
   */
  static hasFunction(module, functionName) {
    return module && typeof module[functionName] === 'function';
  }

  /**
   * Safely call a function in a module with error handling
   * @param {Object} module - The loaded module
   * @param {string} functionName - Name of the function to call
   * @param {Array} args - Arguments to pass to the function
   * @returns {Object} Result with success status and value or error
   */
  static callFunction(module, functionName, ...args) {
    if (!this.hasFunction(module, functionName)) {
      return {
        success: false,
        error: `Function '${functionName}' not found or not callable`
      };
    }

    try {
      const result = module[functionName](...args);
      return {
        success: true,
        value: result
      };
    } catch (e) {
      return {
        success: false,
        error: e.message,
        stack: e.stack
      };
    }
  }
}

/**
 * Class to manage test results
 */
class ResultsManager {
  constructor() {
    this.results = {};
    this.sandboxName = path.basename(__dirname);
  }

  /**
   * Record a test result for an implementation
   * @param {string} implName - Implementation name
   * @param {string} testName - Test name
   * @param {boolean} passed - Whether the test passed
   * @param {string} errorMsg - Optional error message
   */
  recordResult(implName, testName, passed, errorMsg = null) {
    if (!this.results[implName]) {
      this.results[implName] = { passed: 0, failed: 0, skipped: 0, errors: [] };
    }

    if (passed) {
      this.results[implName].passed += 1;
    } else {
      this.results[implName].failed += 1;
      if (errorMsg) {
        this.results[implName].errors.push({
          test: testName,
          error: errorMsg
        });
      }
    }
  }

  /**
   * Record a skipped test for an implementation
   * @param {string} implName - Implementation name
   * @param {string} testName - Test name
   * @param {string} reason - Optional reason for skipping
   */
  recordSkip(implName, testName, reason = null) {
    if (!this.results[implName]) {
      this.results[implName] = { passed: 0, failed: 0, skipped: 0, errors: [] };
    }

    this.results[implName].skipped += 1;
    if (reason) {
      this.results[implName].errors.push({
        test: testName,
        error: `SKIPPED: ${reason}`
      });
    }
  }

  /**
   * Determine the winner based on test results
   * @returns {Array} [winner index, results]
   */
  getWinner() {
    let winner = null;
    let maxPassed = -1;

    for (const [implName, results] of Object.entries(this.results)) {
      if (implName === "original_code") {
        continue; // Skip original code when determining winner
      }

      if (results.passed > maxPassed) {
        maxPassed = results.passed;
        winner = implName;
      } else if (results.passed === maxPassed && winner !== null) {
        if (results.failed < this.results[winner].failed) {
          winner = implName;
        }
      }
    }

    // Convert winner to numeric index if possible
    let winnerIndex = -1;
    if (winner && /modified_code\d+/.test(winner)) {
      const match = winner.match(/(\d+)/);
      if (match) {
        winnerIndex = parseInt(match[1]);
      }
    }

    return [winnerIndex, this.results];
  }

  /**
   * Save test results to a JSON file
   * @param {string} filename - Output filename
   * @returns {Object} Results summary object
   */
  saveResults(filename = "test_results.json") {
    const [winnerIndex, results] = this.getWinner();

    // Check if all tests were skipped
    const allSkipped = Object.entries(results)
      .filter(([implName]) => implName !== "original_code")
      .every(([_, stats]) => {
        return stats.skipped === (stats.passed + stats.failed + stats.skipped);
      });

    const output = {
      winner: winnerIndex,
      all_skipped: allSkipped,
      results: {}
    };

    for (const [name, stats] of Object.entries(results)) {
      if (!name.startsWith("_")) {
        output.results[name] = {
          passed: stats.passed,
          failed: stats.failed,
          skipped: stats.skipped,
          total: stats.passed + stats.failed + stats.skipped
        };
      }
    }

    fs.writeFileSync(filename, JSON.stringify(output, null, 2));
    console.log(`Test results saved to ${filename}`);

    return output;
  }
}

/**
 * Test utility functions specific to this problem domain
 */
class TurnStateTestUtils {
  /**
   * Create test units with controlled action states
   * @param {Array} actingStates - An array with [allyActing, foeActing] booleans
   * @returns {Object} Object with allyStates and foeStates arrays
   */
  static createMockUnits(actingStates = [true, true]) {
    const [allyActing, foeActing] = actingStates;

    const allyStates = [
      { id: 'ally1', hasActed: !allyActing },
      { id: 'ally2', hasActed: true }
    ];

    const foeStates = [
      { id: 'foe1', hasActed: !foeActing },
      { id: 'foe2', hasActed: true }
    ];

    return { allyStates, foeStates };
  }
}

// Load implementations for this specific implementation directory
const implementations = TestUtils.loadAllImplementations();
const resultsManager = new ResultsManager();

// Create global variables immediately
global.__TEST_UTILS__ = TestUtils;
global.__TURN_STATE_TEST_UTILS__ = TurnStateTestUtils;
global.__RESULTS_MANAGER__ = resultsManager;
global.__IMPLEMENTATIONS__ = implementations;

// These global variables are already set up above
// This is just a reminder in the beforeAll hook
beforeAll(() => {
  // Variables already initialized
});

// After all tests run, save the results
afterAll(() => {
  resultsManager.saveResults("test_results.json");
}, 10000); // Ensure enough time for large test suites

// Export for use in tests
module.exports = {
  TestUtils,
  TurnStateTestUtils,
  ResultsManager,
  implementations,
  resultsManager
};

module.exports = {
  presets: [
    ['@babel/preset-env', {targets: {node: 'current'}}]
  ]
};

/**
 * Mock module loader to extract ES modules
 */
const fs = require('fs');
const path = require('path');

// Helper function to load ES modules
function loadESModule(filePath) {
  try {
    const content = fs.readFileSync(filePath, 'utf8');

    // Find the createTurnState function
    const functionMatch = content.match(/function\s+createTurnState\s*\([^)]*\)\s*{[\s\S]*}/);
    if (!functionMatch) {
      throw new Error('Could not find createTurnState function');
    }

    // Get the function code
    const functionCode = functionMatch[0];

    // Create a wrapper to evaluate the function
    const wrapperCode = `
      ${functionCode}
      module.exports = { createTurnState };
    `;

    // Create a temporary file with the evaluated code
    const tempDir = path.dirname(filePath);
    const tempFile = path.join(tempDir, `__temp_${path.basename(filePath)}`);
    fs.writeFileSync(tempFile, wrapperCode);

    // Load the module
    const module = require(tempFile);

    // Clean up
    fs.unlinkSync(tempFile);

    return module;
  } catch (e) {
    console.error(`Error loading ES module ${filePath}:`, e);
    return { __errors__: [e.message] };
  }
}

module.exports = {
  loadESModule
};


import * as THREE from "three";

const world = Globe()
  .globeImageUrl("img/world.topo.200412.3x21600x10800.png")
  .bumpImageUrl("img/earth-topology.png")
  .backgroundImageUrl("img/night-sky.png")(document.getElementById("globeViz"));

// custom globe material
const globeMaterial = world.globeMaterial();
new THREE.TextureLoader().load("img/earth-water.png", (texture) => {
  globeMaterial.specularMap = texture;
  globeMaterial.specular = new THREE.Color("grey");
  globeMaterial.shininess = 10;
});

const directionalLight = world
  .lights()
  .find((light) => light.type === "DirectionalLight");
if (directionalLight) {
  let angle = 0;
  const radius = 360;

  function animateLight() {
    angle += (2 * Math.PI) / 6000; // Full circle in 60 seconds
    directionalLight.position.set(
      radius * Math.cos(angle),
      10,
      radius * Math.sin(angle)
    );
    requestAnimationFrame(animateLight);
  }

  animateLight();
}

// this

const colorScale = d3.scaleSequentialSqrt(d3.interpolateYlOrRd);

// GDP per capita (avoiding countries with small pop)
const getVal = (feat) =>
  feat.properties.GDP_MD_EST / Math.max(1e5, feat.properties.POP_EST);

fetch("../datasets/ne_110m_admin_0_countries.geojson")
  .then((res) => res.json())
  .then((countries) => {
    const maxVal = Math.max(...countries.features.map(getVal));
    colorScale.domain([0, maxVal]);

    const world = new Globe(document.getElementById("globeViz"))
      .globeImageUrl("//unpkg.com/three-globe/example/img/earth-night.jpg")
      .backgroundImageUrl("//unpkg.com/three-globe/example/img/night-sky.png")
      .lineHoverPrecision(0)
      .polygonsData(
        countries.features.filter((d) => d.properties.ISO_A2 !== "AQ")
      )
      .polygonAltitude(0.06)
      .polygonCapColor((feat) => colorScale(getVal(feat)))
      .polygonSideColor(() => "rgba(0, 100, 0, 0.15)")
      .polygonStrokeColor(() => "#111")
      .polygonLabel(
        ({ properties: d }) => `
      ${d.ADMIN} (${d.ISO_A2}):

      GDP: ${d.GDP_MD_EST} M$

      Population: ${d.POP_EST}
    `
      )
      .onPolygonHover((hoverD) =>
        world
          .polygonAltitude((d) => (d === hoverD ? 0.12 : 0.06))
          .polygonCapColor((d) =>
            d === hoverD ? "steelblue" : colorScale(getVal(d))
          )
      )
      .polygonsTransitionDuration(300);
  });

/**
 * Test suite for Globe implementations
 */
const fs = require('fs');
const path = require('path');
const glob = require('glob');

// Find implementation files
const findImplementations = () => {
  const baseDir = path.resolve(__dirname, '..');
  const patterns = [
    'modified_code\\d+\\.js',
    'new_code\\d+\\.js',
    'original_modified_code\\d+\\.js'
  ];

  const regexPattern = new RegExp(patterns.join('|'));
  const files = glob.sync('*.js', { cwd: baseDir }).filter(file => regexPattern.test(file));

  const implementations = {};

  // Load each implementation's source code
  files.forEach(file => {
    const name = path.basename(file, '.js');
    try {
      const filePath = path.join(baseDir, file);
      const sourceCode = fs.readFileSync(filePath, 'utf8');
      implementations[name] = {
        name,
        path: filePath,
        source: sourceCode,
        errors: []
      };
    } catch (e) {
      implementations[name] = {
        name,
        path: path.join(baseDir, file),
        errors: [{ type: 'file', message: e.message }]
      };
    }
  });

  return implementations;
};

// Read instruction
const getInstruction = () => {
  try {
    const instructionPath = path.join(__dirname, '..', 'instruction.txt');
    return fs.readFileSync(instructionPath, 'utf8').trim();
  } catch (e) {
    console.warn('Could not read instruction.txt:', e.message);
    return 'take the globe countries layer from below "// this" and add it to the existing globe';
  }
};

// Create mock test environment
const createMockEnv = () => {
  // Mock Globe instance with chainable methods
  const mockGlobeInstance = {
    globeImageUrl: jest.fn().mockReturnThis(),
    bumpImageUrl: jest.fn().mockReturnThis(),
    backgroundImageUrl: jest.fn().mockReturnThis(),
    polygonsData: jest.fn().mockReturnThis(),
    polygonAltitude: jest.fn().mockReturnThis(),
    polygonCapColor: jest.fn().mockReturnThis(),
    polygonSideColor: jest.fn().mockReturnThis(),
    polygonStrokeColor: jest.fn().mockReturnThis(),
    polygonLabel: jest.fn().mockReturnThis(),
    onPolygonHover: jest.fn().mockReturnThis(),
    polygonsTransitionDuration: jest.fn().mockReturnThis(),
    lineHoverPrecision: jest.fn().mockReturnThis(),
    globeMaterial: jest.fn().mockReturnValue({
      specularMap: null,
      specular: null,
      shininess: 0
    }),
    lights: jest.fn().mockReturnValue([
      { type: 'DirectionalLight', position: { set: jest.fn() } }
    ])
  };

  // Create Globe constructor
  const mockGlobe = jest.fn().mockImplementation(() => {
    // Make callable for Globe()(element) pattern
    const callable = function(element) {
      return mockGlobeInstance;
    };

    // Copy methods to callable
    Object.keys(mockGlobeInstance).forEach(key => {
      callable[key] = mockGlobeInstance[key];
    });

    return callable;
  });

  // Complete environment
  return {
    Globe: mockGlobe,
    THREE: {
      TextureLoader: jest.fn().mockImplementation(() => ({
        load: jest.fn((url, callback) => {
          if (callback) callback({ isTexture: true });
          return { isTexture: true };
        })
      })),
      Color: jest.fn()
    },
    d3: {
      scaleSequentialSqrt: jest.fn().mockImplementation(() => {
        const scale = (val) => '#ff0000';
        scale.domain = jest.fn().mockReturnValue(scale);
        return scale;
      }),
      interpolateYlOrRd: jest.fn()
    },
    document: {
      getElementById: jest.fn().mockReturnValue({ id: 'globeViz' })
    },
    fetch: jest.fn().mockImplementation(() => {
      // Instead of returning a real promise, return a mock object that behaves like a promise
      // but doesn't actually create a pending Promise that could hang the test
      const mockResponse = {
        features: [
          {
            properties: {
              ISO_A2: "US",
              ADMIN: "United States",
              GDP_MD_EST: 19490000,
              POP_EST: 326625791
            }
          },
          {
            properties: {
              ISO_A2: "AQ",
              ADMIN: "Antarctica",
              GDP_MD_EST: 0,
              POP_EST: 1000
            }
          }
        ]
      };

      return {
        json: () => mockResponse,
        then: (callback) => {
          return {
            json: () => mockResponse,
            then: (nextCallback) => {
              if (nextCallback) {
                nextCallback(mockResponse);
              }
              return mockResponse;
            }
          };
        }
      };
    }),
    requestAnimationFrame: jest.fn(cb => {
      // Use Jest's fake timers instead of real setTimeout
      return 0; // Just return a fake ID
    })
  };
};

// Handle implementation module execution
const executeImplementation = (sourceCode) => {
  // Create fresh mocks
  const mockEnv = createMockEnv();

  // Clean code
  const codeToRun = sourceCode
    .replace(/import\s+.*?from.*;?/g, '// import removed')
    .replace(/export\s+.*?;?/g, '// export removed');

  // Execute code
  try {
    const contextKeys = Object.keys(mockEnv);
    const contextValues = Object.values(mockEnv);
    new Function(...contextKeys, codeToRun)(...contextValues);
    return {
      success: true,
      env: mockEnv
    };
  } catch (e) {
    return {
      success: false,
      error: e.message
    };
  }
};

// Run tests directly and collect results
const runTests = (implementations) => {
  const testResults = {};

  // Initialize results for each implementation
  Object.keys(implementations).forEach(implName => {
    testResults[implName] = {
      passed: 0,
      failed: 0,
      skipped: 0,
      total: 0
    };
  });

  // Test each implementation
  Object.entries(implementations).forEach(([implName, impl]) => {
    console.log(`Testing implementation: ${implName}`);

    // Skip implementations with errors
    if (impl.errors && impl.errors.length > 0) {
      console.log(`Implementation ${implName} has errors:`, impl.errors);
      testResults[implName].skipped += 1;
      testResults[implName].total += 1;
      return;
    }

    // Execute the implementation to test it
    const result = executeImplementation(impl.source);

    // If execution failed, mark as failed
    if (!result.success) {
      console.log(`Implementation ${implName} execution failed:`, result.error);

      // For implementations that fail due to variable redeclaration,
      // try to modify the code to remove the redeclaration
      if (result.error.includes("already been declared")) {
        console.log(`Attempting to fix ${implName} for variable redeclaration...`);

        // Modify code to remove redeclaration issues
        // Replace 'const world = ' with 'world = ' for second declaration
        const fixedSource = impl.source.replace(/import.*?from.*?;/g, '// imports removed')
                            .replace(/const\s+world\s*=\s*Globe\(\)/, 'const world = Globe()')
                            .replace(/const\s+world\s*=\s*new\s+Globe/, 'world = new Globe');

        const fixedResult = executeImplementation(fixedSource);

        if (fixedResult.success) {
          console.log(`Fixed ${implName} successfully!`);

          // Execution test passed
          testResults[implName].passed += 1;
          testResults[implName].total += 1;

          // Continue with the fixed result
          const env = fixedResult.env;

          // Test: Globe constructor
          const globeTest = env.Globe.mock.calls.length > 0;
          if (globeTest) {
            testResults[implName].passed += 1;
          } else {
            testResults[implName].failed += 1;
          }
          testResults[implName].total += 1;

          // Only continue if Globe was called
          if (!globeTest) return;

          // Get Globe instance
          const globeInstance = env.Globe.mock.results[0].value;

          // Test: countries data
          const countriesTest = globeInstance.polygonsData.mock.calls.length > 0;
          if (countriesTest) {
            testResults[implName].passed += 1;
          } else {
            testResults[implName].failed += 1;
          }
          testResults[implName].total += 1;

          // Test: fetch for country data
          const fetchTest = env.fetch.mock.calls.length > 0 &&
                            env.fetch.mock.calls[0][0].match(/countries|geojson/i);
          if (fetchTest) {
            testResults[implName].passed += 1;
          } else {
            testResults[implName].failed += 1;
          }
          testResults[implName].total += 1;

          // Test: styling
          const stylingTest = globeInstance.polygonAltitude.mock.calls.length > 0 &&
                              globeInstance.polygonCapColor.mock.calls.length > 0 &&
                              globeInstance.polygonSideColor.mock.calls.length > 0 &&
                              globeInstance.polygonStrokeColor.mock.calls.length > 0;
          if (stylingTest) {
            testResults[implName].passed += 1;
          } else {
            testResults[implName].failed += 1;
          }
          testResults[implName].total += 1;

          // Test: interaction
          const interactionTest = globeInstance.onPolygonHover.mock.calls.length > 0 &&
                                  globeInstance.polygonLabel.mock.calls.length > 0;
          if (interactionTest) {
            testResults[implName].passed += 1;
          } else {
            testResults[implName].failed += 1;
          }
          testResults[implName].total += 1;

          return;
        } else {
          console.log(`Failed to fix ${implName}:`, fixedResult.error);
        }
      }

      testResults[implName].failed += 1;
      testResults[implName].total += 1;
      return;
    }

    // Execution test passed
    testResults[implName].passed += 1;
    testResults[implName].total += 1;

    // Get the environment for more tests
    const env = result.env;

    // Test: Globe constructor
    const globeTest = env.Globe.mock.calls.length > 0;
    if (globeTest) {
      testResults[implName].passed += 1;
    } else {
      testResults[implName].failed += 1;
    }
    testResults[implName].total += 1;

    // Only continue if Globe was called
    if (!globeTest) return;

    // Get Globe instance
    const globeInstance = env.Globe.mock.results[0].value;

    // Test: countries data
    const countriesTest = globeInstance.polygonsData.mock.calls.length > 0;
    if (countriesTest) {
      testResults[implName].passed += 1;
    } else {
      testResults[implName].failed += 1;
    }
    testResults[implName].total += 1;

    // Test: fetch for country data
    const fetchTest = env.fetch.mock.calls.length > 0 &&
                      env.fetch.mock.calls[0][0].match(/countries|geojson/i);
    if (fetchTest) {
      testResults[implName].passed += 1;
    } else {
      testResults[implName].failed += 1;
    }
    testResults[implName].total += 1;

    // Test: styling
    const stylingTest = globeInstance.polygonAltitude.mock.calls.length > 0 &&
                        globeInstance.polygonCapColor.mock.calls.length > 0 &&
                        globeInstance.polygonSideColor.mock.calls.length > 0 &&
                        globeInstance.polygonStrokeColor.mock.calls.length > 0;
    if (stylingTest) {
      testResults[implName].passed += 1;
    } else {
      testResults[implName].failed += 1;
    }
    testResults[implName].total += 1;

    // Test: interaction
    const interactionTest = globeInstance.onPolygonHover.mock.calls.length > 0 &&
                            globeInstance.polygonLabel.mock.calls.length > 0;
    if (interactionTest) {
      testResults[implName].passed += 1;
    } else {
      testResults[implName].failed += 1;
    }
    testResults[implName].total += 1;
  });

  return testResults;
};

// Find winner
const determineWinner = (results) => {
  let winner = -1;
  let maxPassed = -1;

  Object.entries(results).forEach(([implName, stats]) => {
    if (stats.passed > maxPassed) {
      maxPassed = stats.passed;
      const match = implName.match(/(\d+)/);
      if (match) {
        winner = parseInt(match[1], 10);
      }
    }
  });

  return winner;
};

// Main test
describe('Globe Implementation Tests', () => {
  // Use Jest's fake timers for more control
  jest.useFakeTimers();

  // Get implementations
  const implementations = findImplementations();
  const instruction = getInstruction();

  console.log(`Found ${Object.keys(implementations).length} implementations to test`);
  console.log(`Instruction: "${instruction}"`);

  let testResults = {};

  // Run a single test to satisfy Jest
  test('Implementations tested successfully', () => {
    // Direct test execution outside Jest
    testResults = runTests(implementations);

    // Determine winner
    const winner = determineWinner(testResults);

    // Check if all tests were skipped
    const allSkipped = Object.values(testResults).every(
      stats => stats.total === stats.skipped
    );

    // Create final results
    const finalResults = {
      winner,
      all_skipped: allSkipped,
      results: testResults
    };

    // Save results
    const resultPath = path.resolve(__dirname, '..', 'test_results.json');
    fs.writeFileSync(resultPath, JSON.stringify(finalResults, null, 2));
    console.log('Test results saved to test_results.json');

    // Run any pending timers and promises
    jest.runAllTimers();

    // Always pass the test
    expect(true).toBe(true);
  });

  // Cleanup after all tests
  afterAll(() => {
    // Clear any remaining timers
    jest.clearAllTimers();

    // If you're still seeing hanging tests, try providing additional cleanup
    if (global.gc) {
      global.gc(); // Force garbage collection if available
    }
  });
});

Instruction: take the globe countries layer from below "// this" and add it to the existing globe

{
  "name": "js-test-framework",
  "version": "1.0.0",
  "description": "JavaScript testing framework for multiple implementations",
  "main": "index.js",
  "scripts": {
    "test": "jest --forceExit"
  },
  "devDependencies": {
    "jest": "^29.7.0",
    "glob": "^10.3.10"
  },
  "jest": {
    "setupFilesAfterEnv": ["./jest-setup.js"],
    "testEnvironment": "node",
    "testMatch": ["**/tests/**/*.test.js"],
    "verbose": true,
    "collectCoverage": false,
    "transformIgnorePatterns": [],
    "moduleNameMapper": {
      "^three$": "<rootDir>/__mocks__/three.js",
      "^d3$": "<rootDir>/__mocks__/d3.js",
      "\\.png$": "<rootDir>/__mocks__/fileMock.js",
      "\\.jpg$": "<rootDir>/__mocks__/fileMock.js"
    }
  }
}

// jest-setup.js
// This file is intentionally empty as we now handle all testing in test_code.test.js

// Mock for Globe function
class GlobeInstance {
  constructor(domElement) {
    this._domElement = domElement;
    this._properties = {
      globeImageUrl: '',
      bumpImageUrl: '',
      backgroundImageUrl: '',
      polygonsData: [],
      polygonAltitude: 0,
      polygonCapColor: null,
      polygonSideColor: null,
      polygonStrokeColor: null,
      polygonLabel: null,
      polygonsTransitionDuration: 0,
      lineHoverPrecision: 0
    };
    this._globeMaterial = {
      specularMap: null,
      specular: null,
      shininess: 0
    };
    this._lights = [
      { type: 'AmbientLight' },
      { type: 'DirectionalLight', position: { set: jest.fn() } }
    ];
    this._countriesLayerAdded = false;
  }

  // Chainable methods
  globeImageUrl(url) {
    this._properties.globeImageUrl = url;
    return this;
  }

  bumpImageUrl(url) {
    this._properties.bumpImageUrl = url;
    return this;
  }

  backgroundImageUrl(url) {
    this._properties.backgroundImageUrl = url;
    return this;
  }

  globeMaterial() {
    return this._globeMaterial;
  }

  lights() {
    return this._lights;
  }

  polygonsData(data) {
    this._properties.polygonsData = data;
    this._countriesLayerAdded = true;
    return this;
  }

  polygonAltitude(altitude) {
    if (typeof altitude === 'function') {
      this._properties.polygonAltitudeFunc = altitude;
    } else {
      this._properties.polygonAltitude = altitude;
    }
    return this;
  }

  polygonCapColor(colorFn) {
    this._properties.polygonCapColor = colorFn;
    return this;
  }

  polygonSideColor(colorFn) {
    this._properties.polygonSideColor = colorFn;
    return this;
  }

  polygonStrokeColor(colorFn) {
    this._properties.polygonStrokeColor = colorFn;
    return this;
  }

  polygonLabel(labelFn) {
    this._properties.polygonLabel = labelFn;
    return this;
  }

  onPolygonHover(hoverFn) {
    this._properties.onPolygonHover = hoverFn;
    return this;
  }

  polygonsTransitionDuration(duration) {
    this._properties.polygonsTransitionDuration = duration;
    return this;
  }

  lineHoverPrecision(precision) {
    this._properties.lineHoverPrecision = precision;
    return this;
  }

  // Allow checking if countries layer was added
  hasCountriesLayer() {
    return this._countriesLayerAdded;
  }
}

function Globe(domElement) {
  const instance = new GlobeInstance(domElement);

  // Make the instance callable to support the syntax:
  // Globe()....(domElement)
  const callable = function(domElement) {
    instance._domElement = domElement;
    return instance;
  };

  // Copy all properties and methods from instance to callable
  Object.setPrototypeOf(callable, instance);
  Object.getOwnPropertyNames(GlobeInstance.prototype).forEach(name => {
    if (name !== 'constructor') {
      callable[name] = instance[name].bind(instance);
    }
  });

  return callable;
}

module.exports = Globe;

// Mock for fetch
global.fetch = jest.fn().mockImplementation((url) => {
  // Sample GeoJSON data
  const mockCountries = {
    features: [
      {
        properties: {
          ISO_A2: "US",
          ADMIN: "United States",
          GDP_MD_EST: 19490000,
          POP_EST: 326625791
        }
      },
      {
        properties: {
          ISO_A2: "AQ",
          ADMIN: "Antarctica",
          GDP_MD_EST: 0,
          POP_EST: 1000
        }
      },
      {
        properties: {
          ISO_A2: "DE",
          ADMIN: "Germany",
          GDP_MD_EST: 3677000,
          POP_EST: 80594017
        }
      }
    ]
  };

  return Promise.resolve({
    json: () => Promise.resolve(mockCountries)
  });
});

// Mock for requestAnimationFrame
global.requestAnimationFrame = jest.fn(callback => setTimeout(callback, 0));

// Mock for Three.js
class Color {
  constructor(color) {
    this.color = color;
  }
}

class TextureLoader {
  load(url, callback) {
    if (callback) {
      const mockTexture = { isTexture: true };
      setTimeout(() => callback(mockTexture), 0);
    }
    return { isTexture: true };
  }
}

module.exports = {
  Color,
  TextureLoader
};

// Mock for image files
module.exports = 'mock-file';

// Mock for d3.js
function scaleSequentialSqrt(interpolator) {
  const scale = {
    domain: function(domain) {
      scale._domain = domain;
      return scale;
    },
    _domain: [0, 1],
    _interpolator: interpolator,
    __type__: 'scaleSequentialSqrt'
  };

  // Make the scale callable
  const fn = (value) => {
    // Simple linear mapping from domain to range [0, 1]
    if (scale._domain[0] === scale._domain[1]) return 0.5;
    const normalized = (value - scale._domain[0]) / (scale._domain[1] - scale._domain[0]);
    return Math.max(0, Math.min(1, normalized));
  };

  // Copy properties from scale to fn
  Object.setPrototypeOf(fn, scale);
  return fn;
}

const interpolateYlOrRd = (t) => `rgba(255, ${Math.floor(255 * (1-t))}, 0, 1)`;

module.exports = {
  scaleSequentialSqrt,
  interpolateYlOrRd
};

// Mock for document
const document = {
  getElementById: function(id) {
    return { id: id, type: 'DOM_ELEMENT' };
  }
};

module.exports = document;


import React from 'react';
import styles from './CharacterStatUI.module.css';
import Sprite from '../sprite/Sprite';
import SingleCharacterStatUI from '../single-character-stat-ui/SingleCharacterStatUI';
import MockChild from '../mock-child/MockChild';

const CharacterStatUI = ({ charName, level, wpn, hp, atk, spd, def, res }) => {
    const characterStats = [
        { characterStatType: 'NAME', characterStatValue: charName },
        { characterStatType: 'LV', characterStatValue: level },
        { characterStatType: 'WPN', characterStatValue: wpn },
        { characterStatType: 'HP', characterStatValue: hp },
        { characterStatType: 'ATK', characterStatValue: atk },
        { characterStatType: 'SPD', characterStatValue: spd },
        { characterStatType: 'DEF', characterStatValue: def },
        { characterStatType: 'RES', characterStatValue: res },
    ];

    console.log('Character Stats:', {
        charName,
        level,
        wpn,
        hp,
        atk,
        spd,
        def,
        res
    });

    const characterStatsSlice1 = characterStats.slice(0, 4);
    const characterStatsSlice2 = characterStats.slice(4);

    return (

                <MockChild componentName="CharacterStatPortrait" characterName="Alfonse" />

                    {characterStatsSlice1.map((item, index) => (
                        <SingleCharacterStatUI
                            key={index}
                            characterStatType={item.characterStatType}
                            characterStatValue={item.characterStatValue}
                            backgroundColor="white"
                        />
                    ))}

                    {characterStatsSlice2.map((item, index) => (
                        <SingleCharacterStatUI
                            key={index}
                            characterStatType={item.characterStatType}
                            characterStatValue={item.characterStatValue}
                            backgroundColor="white"
                        />
                    ))}

    );
};

export default CharacterStatUI;

//
<Sprite spriteName="PortraitAlfonse" />

import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import fs from 'fs';
import path from 'path';

// Import the implementations directly from the setup file
const { implementations, resultsManager } = require('../jest-setup');

// Testing parameters
const testParams = {
  charName: 'Alfonse',
  level: 40,
  wpn: 'Sword',
  hp: 45,
  atk: 35,
  spd: 25,
  def: 30,
  res: 20
};

// Run basic test to make sure setup works
test('Basic test works', () => {
  expect(true).toBe(true);
});

// Test that implementations were loaded
test('Implementations are loaded', () => {
  expect(implementations).toBeDefined();
  expect(Object.keys(implementations).length).toBeGreaterThan(0);
});

// Test each implementation
Object.keys(implementations).forEach(implName => {
  describe(`Implementation: ${implName}`, () => {
    const implModule = implementations[implName];

    test(`${implName} - Module loads without errors`, () => {
      const hasErrors = implModule.__errors__ && implModule.__errors__.length > 0;

      if (hasErrors) {
        const errorMessage = implModule.__errors__.map(e => e.message).join(', ');
        resultsManager.recordResult(implName, 'module_load', false, errorMessage);
        // Just log error but don't fail test - we want to record result
        console.error(`Module ${implName} failed to load: ${errorMessage}`);
      }

      resultsManager.recordResult(implName, 'module_load', !hasErrors);
      expect(hasErrors).toBe(false);
    });

    // Skip other tests if module has errors
    if (implModule.__errors__ && implModule.__errors__.length > 0) {
      return;
    }

    test(`${implName} - Component is defined`, () => {
      const CharacterStatUI = implModule.default;
      const componentDefined = typeof CharacterStatUI === 'function';

      resultsManager.recordResult(implName, 'component_defined', componentDefined);
      expect(componentDefined).toBe(true);
    });

    test(`${implName} - Component renders without errors`, () => {
      const CharacterStatUI = implModule.default;

      if (typeof CharacterStatUI !== 'function') {
        resultsManager.recordResult(implName, 'component_renders', false, 'Component not defined');
        throw new Error('Component not defined');
      }

      try {
        render(<CharacterStatUI {...testParams} />);
        resultsManager.recordResult(implName, 'component_renders', true);
        expect(true).toBe(true);
      } catch (error) {
        resultsManager.recordResult(implName, 'component_renders', false, error.message);
        throw error;
      }
    });

    test(`${implName} - Component renders all character stats`, () => {
      const CharacterStatUI = implModule.default;

      if (typeof CharacterStatUI !== 'function') {
        resultsManager.recordResult(implName, 'renders_all_stats', false, 'Component not defined');
        throw new Error('Component not defined');
      }

      try {
        render(<CharacterStatUI {...testParams} />);
        const charStats = screen.getAllByTestId('character-stat');

        resultsManager.recordResult(implName, 'renders_all_stats', charStats.length === 8);
        expect(charStats.length).toBe(8);
      } catch (error) {
        resultsManager.recordResult(implName, 'renders_all_stats', false, error.message);
        throw error;
      }
    });

    test(`${implName} - Component renders the Sprite component or MockChild`, () => {
      const CharacterStatUI = implModule.default;

      if (typeof CharacterStatUI !== 'function') {
        resultsManager.recordResult(implName, 'renders_sprite', false, 'Component not defined');
        throw new Error('Component not defined');
      }

      try {
        render(<CharacterStatUI {...testParams} />);
        // Check for either direct Sprite or MockChild
        const sprite = screen.queryByTestId('sprite-component');
        const mockChild = screen.queryByTestId('mock-child');

        const hasSprite = !!sprite;
        const hasMockChild = !!mockChild && mockChild.getAttribute('data-component-name') === 'CharacterStatPortrait';

        // For original code, we only expect MockChild
        if (implName === 'original_code') {
          resultsManager.recordResult(implName, 'renders_sprite', hasMockChild);
          expect(hasMockChild).toBe(true);
        } else {
          // For implementations, we expect direct Sprite
          resultsManager.recordResult(implName, 'renders_sprite', hasSprite);
          expect(hasSprite).toBe(true);
        }
      } catch (error) {
        resultsManager.recordResult(implName, 'renders_sprite', false, error.message);
        throw error;
      }
    });

    test(`${implName} - Sprite has the correct spriteName prop`, () => {
      const CharacterStatUI = implModule.default;

      if (typeof CharacterStatUI !== 'function') {
        resultsManager.recordResult(implName, 'sprite_correct_name', false, 'Component not defined');
        throw new Error('Component not defined');
      }

      try {
        render(<CharacterStatUI {...testParams} />);

        // For original code, we need to check differently
        if (implName === 'original_code') {
          const mockChild = screen.queryByTestId('mock-child');
          const characterName = mockChild?.getAttribute('data-character-name');

          // In the original code, the character name should be Alfonse in the MockChild
          resultsManager.recordResult(implName, 'sprite_correct_name', characterName === 'Alfonse');
          expect(characterName).toBe('Alfonse');
        } else {
          // For implementations, check the Sprite component
          const sprite = screen.queryByTestId('sprite-component');
          const spriteName = sprite?.getAttribute('data-sprite-name');

          resultsManager.recordResult(implName, 'sprite_correct_name', spriteName === 'PortraitAlfonse');
          expect(spriteName).toBe('PortraitAlfonse');
        }
      } catch (error) {
        resultsManager.recordResult(implName, 'sprite_correct_name', false, error.message);
        throw error;
      }
    });

    test(`${implName} - Sprite container has overflow hidden`, () => {
      const CharacterStatUI = implModule.default;

      if (typeof CharacterStatUI !== 'function') {
        resultsManager.recordResult(implName, 'has_overflow_hidden', false, 'Component not defined');
        throw new Error('Component not defined');
      }

      try {
        const { container } = render(<CharacterStatUI {...testParams} />);

        // For original code, we fail this test since it's not implementing the requirement
        if (implName === 'original_code') {
          // Original code doesn't directly use Sprite so it fails this requirement
          resultsManager.recordResult(implName, 'has_overflow_hidden', false, 'Original code does not implement this requirement');
          throw new Error('Original code does not implement this requirement');
        }

        const sprite = screen.getByTestId('sprite-component');

        // Check if the sprite or its parent has overflow hidden
        let overflowHidden = false;
        let element = sprite;

        // Check the sprite itself
        if (element.style.overflow === 'hidden') {
          overflowHidden = true;
        }

        // Check parent elements (up to 3 levels)
        for (let i = 0; i < 3; i++) {
          if (element.parentElement) {
            element = element.parentElement;
            if (element.style.overflow === 'hidden') {
              overflowHidden = true;
              break;
            }
          } else {
            break;
          }
        }

        resultsManager.recordResult(implName, 'has_overflow_hidden', overflowHidden);
        expect(overflowHidden).toBe(true);
      } catch (error) {
        resultsManager.recordResult(implName, 'has_overflow_hidden', false, error.message);
        throw error;
      }
    });

    test(`${implName} - Sprite has proper width/height styling`, () => {
      const CharacterStatUI = implModule.default;

      if (typeof CharacterStatUI !== 'function') {
        resultsManager.recordResult(implName, 'has_sizing_styles', false, 'Component not defined');
        throw new Error('Component not defined');
      }

      try {
        render(<CharacterStatUI {...testParams} />);

        // For original code, we fail this test since it's not implementing the requirement
        if (implName === 'original_code') {
          // Original code doesn't directly use Sprite so it fails this requirement
          resultsManager.recordResult(implName, 'has_sizing_styles', false, 'Original code does not implement this requirement');
          throw new Error('Original code does not implement this requirement');
        }

        const sprite = screen.getByTestId('sprite-component');

        // Check if the sprite or its parent has styles to make it fit
        let hasSizingStyles = false;

        // Check if the sprite itself has width/height styles
        if (sprite.style.width === '100%' || sprite.style.height === '100%') {
          hasSizingStyles = true;
        }

        resultsManager.recordResult(implName, 'has_sizing_styles', hasSizingStyles);
        expect(hasSizingStyles).toBe(true);
      } catch (error) {
        resultsManager.recordResult(implName, 'has_sizing_styles', false, error.message);
        throw error;
      }
    });
  });
});

// After all tests complete, make sure test_results.json is created
afterAll(() => {
  // Save test results
  try {
    if (resultsManager) {
      resultsManager.saveResults();
    } else {
      // Fallback if resultsManager is not available
      console.error('ResultsManager not available, cannot save test results');
    }
  } catch (error) {
    console.error('Error saving test results:', error);
  }
});

Instruction: The following is the CSS style of the React component:  ```css .characterTable {     display: grid;     grid-template-columns: auto 1fr 1fr;     grid-template-rows: 1fr;     gap: 0px;     width: 100%;     max-width: 800px;     margin: 0 auto;     isolation: isolate; }  .characterCell {     display: flex;     flex-direction: column;     gap: 0px;     overflow: hidden; }  .characterHeader {     font-size: 20px;     font-weight: bold;     margin-bottom: 8px; }  .characterLevel {     font-size: 16px;     font-weight: bold;     margin-bottom: 8px; }  .statContainer {     position: relative;     display: inline-block;     width: 100%;     height: 100%;     background-size: cover;     background-position: center;     z-index: 0;     margin-bottom: 0; }  .statText {     position: absolute;     top: 50%;     left: 50%;     transform: translate(-50%, -50%);     width: 100%;     height: 100%;     display: flex;     align-items: center;     justify-content: center;     text-align: center;     font-size: 16px;     color: white;     font-weight: bold;     z-index: 1; }  .Sprite[spriteName="PortraitAlfonse"] { /*This selector targets the specific sprite*/     display: flex;     align-items: center;     padding-left: 8px;     box-sizing: border-box;     width: 20vw;     height: 40px;     min-width: 144px; /* 720 * 0.2 */     min-height: 204.8px; /* 1280 * 0.16 */ } ```  Please make the component <Sprite spriteName="PortraitAlfonse"> to fill inside the <MockChild componentName="CharacterStatPortrait" characterName="Alfonse" />, fit to width or height and the rest overflow hidden.

{
  "name": "js-test-framework",
  "version": "1.0.0",
  "description": "JavaScript testing framework for multiple implementations",
  "main": "index.js",
  "scripts": {
    "test": "jest --config jest.config.js"
  },
  "devDependencies": {
    "jest": "^29.7.0",
    "glob": "^10.3.10",
    "@testing-library/react": "^14.0.0",
    "@testing-library/jest-dom": "^6.1.4",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "jest-environment-jsdom": "^29.7.0",
    "@babel/core": "^7.22.5",
    "@babel/preset-env": "^7.22.5",
    "@babel/preset-react": "^7.22.5",
    "babel-jest": "^29.7.0"
  },
  "jest": "./jest.config.js"
}

// jest-setup.js - Copy this file to each implementation folder
const fs = require('fs');
const path = require('path');
const glob = require('glob');
const { TextEncoder, TextDecoder } = require('util');

// Handle JSX files instead of only JS files
require('@testing-library/jest-dom');

global.TextEncoder = TextEncoder;
global.TextDecoder = TextDecoder;

/**
 * Utility class to handle JavaScript implementations
 */
class TestUtils {
  /**
   * Find all implementation files in the current directory
   * @param {string} directory - Directory to search in (defaults to current directory)
   * @returns {Array<string>} List of implementation file paths
   */
  static discoverImplementationFiles(directory = null) {
    if (!directory) {
      directory = __dirname;
    }

    const patterns = [
      'modified_code\\d+\\.(js|jsx)',
      'new_code\\d+\\.(js|jsx)',
      'implementation\\d*\\.(js|jsx)',
      'original_code\\.(js|jsx)',
      'original_modified_code\\d+\\.(js|jsx)'
    ];

    const regexPattern = new RegExp(patterns.join('|'));
    const implementations = [];

    // Use glob to find matching files
    const files = glob.sync(path.join(directory, '*.{js,jsx}'));

    for (const filePath of files) {
      if (regexPattern.test(path.basename(filePath))) {
        implementations.push(filePath);
      }
    }

    // Sort files numerically
    implementations.sort((a, b) => {
      // Put original code first
      if (path.basename(a).startsWith('original_code.') && !path.basename(b).startsWith('original_code.')) {
        return -1;
      }
      if (!path.basename(a).startsWith('original_code.') && path.basename(b).startsWith('original_code.')) {
        return 1;
      }

      const aMatch = path.basename(a).match(/(\d+)/);
      const bMatch = path.basename(b).match(/(\d+)/);
      const aNum = aMatch ? parseInt(aMatch[1]) : 0;
      const bNum = bMatch ? parseInt(bMatch[1]) : 0;
      return aNum - bNum;
    });

    return implementations;
  }

  /**
   * Safely load a module from a file path
   * @param {string} filePath - Path to the JavaScript file
   * @param {string} moduleName - Optional module name (defaults to filename)
   * @returns {Object} Loaded module with error information if any
   */
  static loadModule(filePath, moduleName = null) {
    if (!moduleName) {
      moduleName = path.basename(filePath).replace(/\.(js|jsx)$/, '');
    }

    // Create unique module name to avoid conflicts
    const sandboxId = path.basename(path.dirname(filePath));
    const uniqueModuleName = `${sandboxId}_${moduleName}`;

    try {
      // Read file contents
      const sourceCode = fs.readFileSync(filePath, 'utf8');

      // Create module object
      const moduleObj = {
        __file__: filePath,
        __name__: uniqueModuleName,
        __display_name__: moduleName,
        __source__: sourceCode, // Store source code for JSX handling
        __errors__: [] // Track errors in the module
      };

      try {
        // Skip syntax validation for JSX files - we'll let babel handle that
        if (!filePath.endsWith('.jsx')) {
          // Try to test-compile the code to check for syntax errors
          new Function(sourceCode);
        }
      } catch (e) {
        const errorMsg = `Syntax error: ${e.message}`;
        console.error(`Syntax error in ${filePath}: ${e.message}`);
        console.error(`  Line ${e.lineNumber}, column ${e.columnNumber}`);

        // Record the error but continue loading what we can
        moduleObj.__errors__.push({
          type: 'syntax',
          message: errorMsg,
          lineNumber: e.lineNumber,
          columnNumber: e.columnNumber
        });
      }

      try {
        // Try to require the module even if there were syntax errors
        // This may or may not succeed

        // Clear the require cache to ensure fresh load
        if (require.cache[require.resolve(filePath)]) {
          delete require.cache[require.resolve(filePath)];
        }

        const loadedModule = require(filePath);

        // Copy all properties from the loaded module
        for (const key in loadedModule) {
          if (Object.prototype.hasOwnProperty.call(loadedModule, key)) {
            moduleObj[key] = loadedModule[key];
          }
        }
      } catch (e) {
        const errorMsg = `Runtime error: ${e.message}`;
        console.error(`Error executing module ${filePath}: ${e.message}`);
        console.error(e.stack);

        // Record the runtime error
        moduleObj.__errors__.push({
          type: 'runtime',
          message: errorMsg,
          stack: e.stack
        });
      }

      return moduleObj;
    } catch (e) {
      const moduleObj = {
        __file__: filePath,
        __name__: uniqueModuleName,
        __display_name__: moduleName,
        __errors__: []
      };

      if (e.code === 'ENOENT') {
        const errorMsg = `File not found: ${e.message}`;
        console.error(`Error: ${errorMsg}`);
        moduleObj.__errors__.push({
          type: 'file',
          message: errorMsg
        });
      } else {
        const errorMsg = `Unexpected error: ${e.message}`;
        console.error(`Error loading module ${filePath}: ${e.message}`);
        moduleObj.__errors__.push({
          type: 'unknown',
          message: errorMsg
        });
      }

      return moduleObj;
    }
  }

  /**
   * Load all implementation files in the directory
   * @param {string} directory - Directory to search in (defaults to current directory)
   * @returns {Object} Dictionary mapping module names to loaded modules
   */
  static loadAllImplementations(directory = null) {
    if (!directory) {
      directory = __dirname;
    }

    const implementations = {};

    const implementationFiles = this.discoverImplementationFiles(directory);
    if (implementationFiles.length === 0) {
      console.warn("WARNING: No implementation files found. Check your file naming patterns.");
    }

    for (const filePath of implementationFiles) {
      const moduleName = path.basename(filePath).replace(/\.(js|jsx)$/, '');
      const module = this.loadModule(filePath, moduleName);

      // Always add the module, even if it has errors
      implementations[moduleName] = module;

      if (module.__errors__ && module.__errors__.length > 0) {
        console.log(`Loaded with errors: ${moduleName} - ${module.__errors__.length} errors found`);
        module.__errors__.forEach(err => console.log(`  - ${err.type}: ${err.message}`));
      } else {
        console.log(`Successfully loaded: ${moduleName}`);
      }
    }

    return implementations;
  }

  /**
   * Check if a function exists in a module and is callable
   * @param {Object} module - The loaded module
   * @param {string} functionName - Name of the function to test
   * @returns {boolean} Whether the function exists and is callable
   */
  static hasFunction(module, functionName) {
    return module && typeof module[functionName] === 'function';
  }

  /**
   * Safely call a function in a module with error handling
   * @param {Object} module - The loaded module
   * @param {string} functionName - Name of the function to call
   * @param {Array} args - Arguments to pass to the function
   * @returns {Object} Result with success status and value or error
   */
  static callFunction(module, functionName, ...args) {
    if (!this.hasFunction(module, functionName)) {
      return {
        success: false,
        error: `Function '${functionName}' not found or not callable`
      };
    }

    try {
      const result = module[functionName](...args);
      return {
        success: true,
        value: result
      };
    } catch (e) {
      return {
        success: false,
        error: e.message,
        stack: e.stack
      };
    }
  }
}

/**
 * Class to manage test results
 */
class TestResultsManager {
  constructor() {
    this.results = {};
    this.sandboxName = path.basename(__dirname);
  }

  /**
   * Record a test result for an implementation
   * @param {string} implName - Implementation name
   * @param {string} testName - Test name
   * @param {boolean} passed - Whether the test passed
   * @param {string} errorMsg - Optional error message
   */
  recordResult(implName, testName, passed, errorMsg = null) {
    if (!this.results[implName]) {
      this.results[implName] = {
        passed: 0,
        failed: 0,
        skipped: 0,
        errors: [],
        // Track tests to ensure we don't count duplicates
        tests: new Set()
      };
    }

    // Only count the test once, even if it's recorded multiple times
    if (!this.results[implName].tests.has(testName)) {
      this.results[implName].tests.add(testName);

      if (passed) {
        this.results[implName].passed += 1;
      } else {
        this.results[implName].failed += 1;
      }
    } else {
      // If we've already counted this test but the result changed from pass to fail, update counts
      if (!passed && this.results[implName][testName] === 'passed') {
        this.results[implName].passed -= 1;
        this.results[implName].failed += 1;
        this.results[implName][testName] = 'failed';
      }
    }

    // Always record the test state for potential updates
    this.results[implName][testName] = passed ? 'passed' : 'failed';

    // Record error if provided
    if (errorMsg) {
      this.results[implName].errors.push({
        test: testName,
        error: errorMsg
      });
    }
  }

  /**
   * Record a skipped test for an implementation
   * @param {string} implName - Implementation name
   * @param {string} testName - Test name
   * @param {string} reason - Optional reason for skipping
   */
  recordSkip(implName, testName, reason = null) {
    if (!this.results[implName]) {
      this.results[implName] = {
        passed: 0,
        failed: 0,
        skipped: 0,
        errors: [],
        tests: new Set()
      };
    }

    // Only count the test once, even if it's recorded multiple times
    if (!this.results[implName].tests.has(testName)) {
      this.results[implName].tests.add(testName);
      this.results[implName].skipped += 1;
    } else {
      // If test was previously passed or failed, update counts
      if (this.results[implName][testName] === 'passed') {
        this.results[implName].passed -= 1;
        this.results[implName].skipped += 1;
      } else if (this.results[implName][testName] === 'failed') {
        this.results[implName].failed -= 1;
        this.results[implName].skipped += 1;
      }
    }

    // Record the test state
    this.results[implName][testName] = 'skipped';

    if (reason) {
      this.results[implName].errors.push({
        test: testName,
        error: `SKIPPED: ${reason}`
      });
    }
  }

  /**
   * Determine the winner based on test results
   * @returns {Array} [winner index, results]
   */
  getWinner() {
    let winner = null;
    let maxPassed = -1;

    for (const [implName, results] of Object.entries(this.results)) {
      if (implName === "original_code") {
        continue; // Skip original code when determining winner
      }

      if (results.passed > maxPassed) {
        maxPassed = results.passed;
        winner = implName;
      } else if (results.passed === maxPassed && winner !== null) {
        if (results.failed < this.results[winner].failed) {
          winner = implName;
        }
      }
    }

    // Convert winner to numeric index if possible
    let winnerIndex = -1;
    if (winner && /modified_code\d+/.test(winner)) {
      const match = winner.match(/(\d+)/);
      if (match) {
        winnerIndex = parseInt(match[1]);
      }
    }

    return [winnerIndex, this.results];
  }

  /**
   * Save test results to a JSON file
   * @param {string} filename - Output filename
   * @returns {Object} Results summary object
   */
  saveResults(filename = "test_results.json") {
    const [winnerIndex, results] = this.getWinner();

    // Check if all tests were skipped
    const allSkipped = Object.entries(results)
      .filter(([implName]) => implName !== "original_code")
      .every(([_, stats]) => {
        return stats.skipped === (stats.passed + stats.failed + stats.skipped);
      });

    const output = {
      winner: winnerIndex,
      all_skipped: allSkipped,
      results: {}
    };

    for (const [name, stats] of Object.entries(results)) {
      if (!name.startsWith("_")) {
        // Use the size of the tests Set to get an accurate count of total tests
        const totalTests = stats.tests ? stats.tests.size : stats.passed + stats.failed + stats.skipped;

        output.results[name] = {
          passed: stats.passed,
          failed: stats.failed,
          skipped: stats.skipped,
          total: totalTests
        };
      }
    }

    fs.writeFileSync(filename, JSON.stringify(output, null, 2));
    console.log(`Test results saved to ${filename}`);

    return output;
  }
}

// Load implementations for this specific implementation directory
const implementations = TestUtils.loadAllImplementations();
const resultsManager = new TestResultsManager();

// Set up global variables for Jest tests
beforeAll(() => {
  global.__TEST_UTILS__ = TestUtils;
  global.__RESULTS_MANAGER__ = resultsManager;
  global.__IMPLEMENTATIONS__ = implementations;

  // Attach to global object for direct access in tests
  global.TestUtils = TestUtils;
  global.implementations = implementations;
  global.resultsManager = resultsManager;
});

// After all tests run, save the results
afterAll(() => {
  resultsManager.saveResults();
});

// Export for use in tests
module.exports = {
  TestUtils,
  TestResultsManager,
  implementations,
  resultsManager
};

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        targets: {
          node: 'current',
        },
      },
    ],
    '@babel/preset-react',
  ],
};

module.exports = {
  setupFilesAfterEnv: ['./jest-setup.js'],
  testEnvironment: 'jsdom',
  testMatch: ['**/tests/**/*.test.js'],
  verbose: true,
  collectCoverage: true,
  coverageDirectory: './coverage',
  collectCoverageFrom: [
    './*.jsx',
    '!jest-setup.js',
    '!babel.config.js',
    '!jest.config.js'
  ],
  moduleNameMapper: {
    '\\.module\\.css$': '<rootDir>/__mocks__/styleMock.js',
    '\\.css$': '<rootDir>/__mocks__/styleMock.js',
    '^../sprite/Sprite$': '<rootDir>/__mocks__/Sprite.js',
    '^../single-character-stat-ui/SingleCharacterStatUI$': '<rootDir>/__mocks__/SingleCharacterStatUI.js',
    '^../mock-child/MockChild$': '<rootDir>/__mocks__/MockChild.js'
  },
  transform: {
    '^.+\\.(js|jsx)$': 'babel-jest'
  }
};

import React from 'react';

const SingleCharacterStatUI = ({ characterStatType, characterStatValue, backgroundColor }) => {
  return (
    <div data-testid="character-stat" data-stat-type={characterStatType} data-stat-value={characterStatValue}>
      {characterStatType}: {characterStatValue}
    </div>
  );
};

export default SingleCharacterStatUI;

import React from 'react';

const MockChild = ({ componentName, characterName, children }) => {
  return (
    <div data-testid="mock-child" data-component-name={componentName} data-character-name={characterName}>
      {children}
    </div>
  );
};

export default MockChild;

// Mock for CSS modules
module.exports = {};

import React from 'react';

const Sprite = ({ spriteName, style }) => {
  return (
    <div data-testid="sprite-component" data-sprite-name={spriteName} style={style}>
      {spriteName}
    </div>
  );
};

export default Sprite;