# Anti-Cheat Script for oTree Experiments This directory contains anti-cheat protection scripts to prevent participants from cheating during experimental tasks. ## Features The `anti_cheat.js` script provides comprehensive protection against common cheating methods: - **Right-Click Prevention**: Blocks context menu access - **Text Selection Prevention**: Prevents copying text (except in input fields) - **Copy/Paste Prevention**: Blocks clipboard operations - **Keyboard Shortcuts Blocking**: Prevents access to developer tools (F12, Ctrl+Shift+I, etc.) - **DevTools Detection**: Detects when developer tools are opened - **Window Focus Tracking**: Tracks when participants switch tabs or windows - **Screenshot Detection**: Attempts to detect Print Screen usage - **Drag & Drop Prevention**: Blocks dragging elements ## Quick Start ### Basic Integration Add this script to any oTree HTML page where you want anti-cheat protection: ```html {{ block scripts }} {{ endblock }} ``` ### For Live Pages (with oTree's liveSend) The script automatically integrates with oTree's live pages and will send cheating attempt data to the server if `liveSend` is available. Example in your `__init__.py`: ```python class TaskPage(Page): live_method = 'handle_live_data' @staticmethod def handle_live_data(player, data): if data.get('type') == 'cheat_attempt': # Log cheating attempt attempt_type = data.get('attempt_type') total_attempts = data.get('total_attempts') focus_losses = data.get('focus_losses') # Store in your Player model player.cheating_attempts = total_attempts player.focus_losses = focus_losses return {player.id_in_group: {}} # Acknowledge receipt ``` ### Complete Example **1. In your HTML template (e.g., `TaskPage.html`):** ```html {% block title %} Task {% endblock %} {% block content %}
Please complete the task below.
{% formfields %} {% next_button %} {% endblock %} {{ block scripts }} {{ endblock }} ``` **2. In your `__init__.py`, add fields to track cheating:** ```python class Player(BasePlayer): # ... your existing fields ... # Anti-cheat tracking cheating_attempts = models.IntegerField(initial=0, blank=True) focus_losses = models.IntegerField(initial=0, blank=True) class TaskPage(Page): form_model = 'player' form_fields = ['your_task_fields'] @staticmethod def before_next_page(player, timeout_happened): # The hidden fields will be automatically submitted # You can access them here if needed pass ``` ## Configuration You can customize the anti-cheat behavior by configuring it in your HTML page: ```html {% block scripts %} {% endblock %} ``` ## API Reference The script exposes a global `window.AntiCheat` object with the following methods: ### `AntiCheat.getAttempts()` Returns the total number of cheating attempts detected. ```javascript const attempts = window.AntiCheat.getAttempts(); console.log('Total cheating attempts:', attempts); ``` ### `AntiCheat.getFocusLosses()` Returns the number of times the participant lost focus (switched tabs/windows). ```javascript const losses = window.AntiCheat.getFocusLosses(); console.log('Focus losses:', losses); ``` ### `AntiCheat.configure(options)` Updates the configuration options. ```javascript window.AntiCheat.configure({ showWarnings: false // Disable warning popups }); ``` ### `AntiCheat.showWarning(message)` Manually display a warning message. ```javascript window.AntiCheat.showWarning('Bitte bleiben Sie auf dieser Seite.'); ``` ## Data Collection The script automatically creates hidden form fields that will be submitted with your page: - `cheating_attempts`: Total number of cheating attempts - `focus_losses`: Number of times window focus was lost These values are automatically included in the form submission. To capture them in your oTree app, add corresponding fields to your Player model: ```python class Player(BasePlayer): cheating_attempts = models.IntegerField(blank=True) focus_losses = models.IntegerField(blank=True) ``` Then include them in your page's `form_fields`: ```python class TaskPage(Page): form_model = 'player' form_fields = ['your_task_answer', 'cheating_attempts', 'focus_losses'] ``` ## Live Page Integration For pages using oTree's live method, the script will automatically send real-time updates: ```python def live_method(player, data): if data.get('type') == 'cheat_attempt': # Handle cheating attempt attempt_type = data['attempt_type'] # e.g., "Right-click attempt" total_attempts = data['total_attempts'] focus_losses = data['focus_losses'] timestamp = data['timestamp'] # You can store this in a custom model or take action print(f"Player {player.id_in_group}: {attempt_type}") # Optional: Create a log entry CheatLog.create( player=player, attempt_type=attempt_type, timestamp=timestamp ) return {} ``` ## Detected Attempt Types The following attempt types can be detected and logged: - `"Right-click attempt"` - `"Copy attempt"` - `"Cut attempt"` - `"Paste attempt"` - `"F12 key press"` - `"Ctrl+Shift+I"` (DevTools) - `"Ctrl+Shift+J"` (Console) - `"Ctrl+Shift+C"` (Inspect) - `"Ctrl+U"` (View Source) - `"Ctrl+S"` (Save) - `"Ctrl+P"` (Print) - `"Ctrl+C"` (Copy shortcut) - `"Cmd+Option+I (Mac)"` (DevTools) - `"Cmd+Option+J (Mac)"` (Console) - `"Cmd+Option+C (Mac)"` (Inspect) - `"DevTools opened (size detection)"` - `"Console usage detected"` - `"Window focus lost (tab/window switch)"` - `"Page visibility lost (tab change)"` - `"Print Screen key"` ## Important Notes ### Limitations 1. **Complete prevention is impossible**: Determined participants can still find ways to cheat (e.g., taking photos with phone, using secondary devices) 2. **Browser differences**: Some features work differently across browsers 3. **User experience**: Too aggressive anti-cheat can frustrate legitimate participants ### Best Practices 1. **Use selectively**: Only apply to critical task pages, not instructions or consent pages 2. **Test thoroughly**: Check on different browsers (Chrome, Firefox, Safari) 3. **Inform participants**: Include in your instructions that monitoring is in place 4. **Balance security and UX**: Consider what level of protection is truly necessary 5. **Review logs**: Regularly check for false positives ### Ethical Considerations - Inform participants that their actions are being monitored - Include this in your consent form/information sheet - Consider whether the data is necessary for your research - Comply with your institution's ethics requirements and GDPR ## Examples for Different Page Types ### Example 1: Simple Task Page ```html {% block content %}Count the number of 7s in the image below:
Please read the following instructions carefully...
{% next_button %} {% endblock %} ``` ## Troubleshooting ### Script not loading - Verify the file path in the `static` call - Check browser console for errors - Ensure the file is in `_static/anti_cheat/` directory ### Warnings not showing - Check if `showWarnings` is set to `true` in configuration - Verify browser doesn't block the warning div (check CSS z-index) ### Data not being saved - Ensure Player model has `cheating_attempts` and `focus_losses` fields - Include these fields in `form_fields` on your Page class - Check browser console for JavaScript errors ### False positives - Adjust configuration to be less aggressive - Consider disabling certain features (e.g., `blockCopyPaste` if participants need to paste from instructions) ## File Structure ``` anti_cheat/ ├── anti_cheat.js # Main anti-cheat script └── README.md # This file (documentation) ``` ## Support For questions or issues with this anti-cheat system, please refer to: - oTree documentation: https://otree.readthedocs.io/ - This README file - Your project's main documentation