Card format randomizer (helpful to prevent card recognition by varying its appearance)

The ultimate goal is to use AI to come up with synonyms and different ways of asking the same question.

For now, here’s a way to randomize the format of cards to prevent recognition. Here’s a demo:

Original:

image

Random format variations:

  1. image

  2. image

I’ve only tested this out briefly, so am not certain of the stability etc. So far it seems to be working well.

To do this:

Go to tools > manage note types > front template. For Anking/AnkiHub note types, scroll down and paste this below the area that reads:

<!--
ANKIHUB_END
Text below this comment will not be modified by AnkiHub or AnKing add-ons.
Do not edit or remove this comment if you want to protect the content below.
-->

Text to copy/paste below that section:

<script>
// Fonts that are readable on dark backgrounds
var fontFamily = [
    "'Arial'", "'Helvetica'", "'Roboto'", "'Open Sans'", "'Lato'",
    "'Montserrat'", "'Source Sans Pro'", "'Nunito'", "'Raleway'",
    "'Ubuntu'", "'Poppins'", "'Fira Sans'", "'PT Sans'", "'Titillium Web'",
    "'Rubik'", "'Work Sans'", "'Merriweather Sans'", "'Exo 2'", "'Karla'"
];

// Colors suitable for dark backgrounds
var colors = [
    { color: '#E69A8D', name: 'Light Coral Pink' },
    { color: '#ADEFD1', name: 'Pale Mint Green' },
    { color: '#D6ED17', name: 'Bright Lime Green' },
    { color: '#FEE715', name: 'Bright Yellow' },
    { color: '#C7D3D4', name: 'Light Grayish Blue' },
    { color: '#E94B3C', name: 'Bright Red' },
    { color: '#FFE77A', name: 'Pale Yellow' },
    { color: '#E0E0E0', name: 'Light Gray' },
    { color: '#BB86FC', name: 'Light Purple' },
    { color: '#03DAC5', name: 'Teal' },
    { color: '#CF6679', name: 'Pink' },
    { color: '#FFB300', name: 'Amber' },
    { color: '#64FFDA', name: 'Mint' },
    { color: '#FF4081', name: 'Pink Accent' },
    { color: '#B388FF', name: 'Light Purple Accent' },
    { color: '#1DE9B6', name: 'Teal Accent' },
    { color: '#FF9E80', name: 'Deep Orange Accent' }
];

var fontSize = ["18px", "20px", "22px", "24px", "26px"];
var fontWeight = ["normal", "bold", "lighter", "bolder"];
var fontStyle = ["normal", "italic"];
var wordSpacing = ["normal", "2px", "4px", "6px"];
var letterSpacing = ["normal", "1px", "2px", "3px"];
var textShadow = ["none", "1px 1px 2px rgba(0,0,0,0.5)", "2px 2px 4px rgba(0,0,0,0.75)"];

// Set dark background
document.body.style.backgroundColor = '#2A2A2A'; // Dark gray background

// Random selections
var randFontIndex = Math.floor(Math.random() * fontFamily.length);
var randColorIndex = Math.floor(Math.random() * colors.length);
var randFontSizeIndex = Math.floor(Math.random() * fontSize.length);
var randFontWeightIndex = Math.floor(Math.random() * fontWeight.length);
var randFontStyleIndex = Math.floor(Math.random() * fontStyle.length);
var randWordSpacingIndex = Math.floor(Math.random() * wordSpacing.length);
var randLetterSpacingIndex = Math.floor(Math.random() * letterSpacing.length);
var randTextShadowIndex = Math.floor(Math.random() * textShadow.length);

var textAlign = ["center", "left", "right", "justify"];
var textTransform = ["none", "uppercase", "lowercase", "capitalize"];
var randTextAlignIndex = Math.floor(Math.random() * textAlign.length);
var randTextTransformIndex = Math.floor(Math.random() * textTransform.length);

// Apply styles to the text content only, excluding countdown timer
function applyRandomStylesToTextContent() {
    var contentElement = document.getElementById('text'); // Ensure text has this id
    if (contentElement) {
        // Apply styles
        contentElement.style.fontFamily = fontFamily[randFontIndex];
        contentElement.style.color = colors[randColorIndex].color;
        contentElement.style.fontSize = fontSize[randFontSizeIndex];
        contentElement.style.fontWeight = fontWeight[randFontWeightIndex];
        contentElement.style.fontStyle = fontStyle[randFontStyleIndex];
        contentElement.style.textDecoration = "none"; // Ensure no underlining
        contentElement.style.wordSpacing = wordSpacing[randWordSpacingIndex];
        contentElement.style.letterSpacing = letterSpacing[randLetterSpacingIndex];
        contentElement.style.textShadow = textShadow[randTextShadowIndex];
        contentElement.style.textAlign = textAlign[randTextAlignIndex];
        contentElement.style.textTransform = textTransform[randTextTransformIndex];
    }
}

// Function to insert random line breaks between words (not in the middle of words or near punctuation)
function insertRandomLineBreaks(element) {
    var walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, null, false);
    var textNodes = [];
    var node;

    // Collect all text nodes
    while (node = walker.nextNode()) {
        if (node.nodeValue.trim() !== '') {
            textNodes.push(node);
        }
    }

    var numLineBreaks = Math.floor(Math.random() * 5); // 0 to 4 line breaks

    // Insert line breaks between words
    for (var i = 0; i < numLineBreaks; i++) {
        if (textNodes.length > 1) {
            var index = Math.floor(Math.random() * (textNodes.length - 1)) + 1;
            var targetNode = textNodes[index];
            var textContent = targetNode.nodeValue;

            // Find a valid position to insert a line break (after a space, not near punctuation)
            var validPositions = [];
            for (var j = 0; j < textContent.length; j++) {
                if (textContent[j] === ' ' && !/[.,;!?-]/.test(textContent[j + 1]) && !/[.,;!?-]/.test(textContent[j - 1])) {
                    validPositions.push(j);
                }
            }

            if (validPositions.length > 0) {
                var breakPosition = validPositions[Math.floor(Math.random() * validPositions.length)];
                
                // Create a new node for the text before and after the break
                var beforeBreak = document.createTextNode(textContent.slice(0, breakPosition));
                var afterBreak = document.createTextNode(textContent.slice(breakPosition + 1));
                
                // Create a line break
                var newLine = document.createElement('br');

                // Create a new span to hold the original text content and the line break
                var tempElement = document.createElement('span');
                tempElement.appendChild(beforeBreak);
                tempElement.appendChild(newLine);
                tempElement.appendChild(afterBreak);

                // Replace targetNode with the new span
                targetNode.parentNode.replaceChild(tempElement, targetNode);
            }
        }
    }
}

// Apply random line breaks to the content
function applyRandomLineBreaks() {
    var contentElement = document.getElementById('text'); // Ensure text has this id
    if (contentElement) {
        insertRandomLineBreaks(contentElement);
    }
}

// Apply styles and line breaks immediately, excluding countdown timer
(function() {
    applyRandomStylesToTextContent();
    applyRandomLineBreaks();
})();
</script>
</div>

Press save. FYI that sometimes the preview isn’t 100% accurate.

Open to all thoughts/suggestions on how to improve (or why this might not be a good idea). Thanks

1 Like