"use strict"; /* ================= age bands ================= */ var BANDS = { 1: { name: "naya account (0–7 din)", min: 3, max: 10, capStart: 0.05, dropPeriod: 0.9, aposDrop: 0.35, runOn: 0.3 }, 2: { name: "2–4 haftay", min: 4, max: 15, capStart: 0.1, dropPeriod: 0.75, aposDrop: 0.3, runOn: 0.22 }, 3: { name: "1–3 mahine", min: 8, max: 30, capStart: 0.3, dropPeriod: 0.55, aposDrop: 0.22, runOn: 0.1 }, 4: { name: "purana account (3+ mahine)", min: 12, max: 48, capStart: 0.5, dropPeriod: 0.4, aposDrop: 0.15, runOn: 0.05 } }; /* ================= lambai (length) ================= */ var LENGTH_LABEL = { chhota: "Chhota", darmiyana: "Darmiyana", detail: "Detail wala" }; function getEffectiveBand(band, len) { var base = BANDS[band]; var out = { name: base.name, min: base.min, max: base.max, capStart: base.capStart, dropPeriod: base.dropPeriod, aposDrop: base.aposDrop, runOn: base.runOn }; if (len === "chhota") { out.max = Math.max(6, Math.round(base.max * 0.6)); out.min = Math.max(3, Math.round(base.min * 0.6)); } else if (len === "detail") { if (band === 1) { out.min = 5; out.max = 16; } else if (band === 2) { out.min = 9; out.max = 28; } else if (band === 3) { out.min = 20; out.max = 55; } else { out.min = 58; out.max = 105; out.capStart = 0.55; out.dropPeriod = 0.3; } } out.lenLabel = LENGTH_LABEL[len] || "Darmiyana"; return out; } function EB(band) { return getEffectiveBand(band, (typeof state !== "undefined" && state.lengthSel) ? state.lengthSel : "darmiyana"); } var DETAIL_BEATS = [ "same thing happened to me a while back and i ignored it for like a week, which only made it worse", "at first i thought it was just me, then i started noticing it everywhere", "i wasted way too much time on this, tried two or three different ways and none of it really stuck", "the annoying part is how it becomes an everyday thing, sounds small but it wears you down", "a friend told me about this ages ago and i brushed it off, then i saw it happen myself", "what surprised me most was how simple the actual fix turned out to be in the end", "looking back i probably made it way harder than it needed to be, honestly", "if anyone else runs into this, start with the smallest thing first, thats my only real advice", "doesnt play out the same for everyone obviously, just saying how it went for me", "it went on like that for weeks before i finally got fed up and looked into it properly", "the detail that stuck with me was how nobody around seemed to notice it at all", "i still think about it sometimes because the timing of it was just so weird" ]; function rnd(n) { return Math.floor(Math.random() * n); } function pick(arr) { return arr[rnd(arr.length)]; } function chance(p) { return Math.random() < p; } function wordCount(s) { var w = s.trim().split(/\s+/).filter(Boolean); return s.trim() ? w.length : 0; } /* ================= AI-phrase blocklist (both modes) ================= */ var BLOCKLIST = [ "great question", "thanks for sharing", "thank you for sharing", "totally agree with you", "i completely agree", "couldn't agree more", "could not agree more", "at the end of the day", "it's worth noting", "its worth noting", "it is worth noting", "this is so important", "delve", "moreover", "furthermore", "in conclusion", "in summary", "needless to say", "in today's world", "in todays world", "when it comes to", "plays a crucial role", "crucial role", "firstly", "secondly", "lastly", "i hope this helps", "hope this helps", "feel free to", "don't hesitate to", "do not hesitate to", "it's important to note", "it is important to note", "in the realm of", "game changer", "game-changer", "best ever", "must buy", "must-buy", "highly recommend", "amazing product", "you need this", "life changing", "life-changing", "dont miss out", "don't miss out", "limited time" ]; function scrubAI(text) { var out = text; for (var i = 0; i < BLOCKLIST.length; i++) { var phrase = BLOCKLIST[i]; var idx = out.toLowerCase().indexOf(phrase); while (idx !== -1) { out = out.slice(0, idx) + out.slice(idx + phrase.length); idx = out.toLowerCase().indexOf(phrase); } } out = out.replace(/\s+([,.!?])/g, "$1") .replace(/,\s*,/g, ",") .replace(/^\s*,\s*/, "") .replace(/\s{2,}/g, " ") .replace(/^\s*[.!]\s*/, ""); return out.trim(); } /* ================= contractions ================= */ var CONTRACTIONS = [ [/\bdo not\b/gi, "don't"], [/\bdoes not\b/gi, "doesn't"], [/\bdid not\b/gi, "didn't"], [/\bcannot\b/gi, "can't"], [/\bcan not\b/gi, "can't"], [/\bwill not\b/gi, "won't"], [/\bwould not\b/gi, "wouldn't"], [/\bshould not\b/gi, "shouldn't"], [/\bcould not\b/gi, "couldn't"], [/\bis not\b/gi, "isn't"], [/\bare not\b/gi, "aren't"], [/\bwas not\b/gi, "wasn't"], [/\bwere not\b/gi, "weren't"], [/\bhave not\b/gi, "haven't"], [/\bhas not\b/gi, "hasn't"], [/\bI am\b/g, "i'm"], [/\bit is\b/gi, "it's"], [/\bthat is\b/gi, "that's"], [/\bthere is\b/gi, "there's"], [/\byou are\b/gi, "you're"], [/\bwe are\b/gi, "we're"], [/\bthey are\b/gi, "they're"], [/\bI have\b/g, "i've"], [/\bI will\b/g, "i'll"], [/\byou will\b/gi, "you'll"], [/\blet us\b/gi, "let's"], [/\bwhat is\b/gi, "what's"], [/\bhere is\b/gi, "here's"], [/\bit will\b/gi, "it'll"] ]; function forceContractions(text) { var out = text; for (var i = 0; i < CONTRACTIONS.length; i++) out = out.replace(CONTRACTIONS[i][0], CONTRACTIONS[i][1]); if (chance(0.55)) out = out.replace(/\bkind of\b/gi, "kinda"); if (chance(0.4)) out = out.replace(/\bsort of\b/gi, "sorta"); if (chance(0.45)) out = out.replace(/\bgoing to\b/gi, "gonna"); if (chance(0.3)) out = out.replace(/\bwant to\b/gi, "wanna"); if (chance(0.25)) out = out.replace(/\bbecause\b/gi, "cuz"); return out; } /* ================= roughening ================= */ function roughen(text, band) { var b = EB(band); var out = forceContractions(text); out = scrubAI(out); // sentence start: mostly lowercase, older accounts capitalize more if (chance(b.capStart)) out = out.charAt(0).toUpperCase() + out.slice(1); else out = out.charAt(0).toLowerCase() + out.slice(1); // standalone "I" often lowercase for young accounts if (band <= 2 && chance(0.6)) out = out.replace(/ I /g, " i "); // run-on: merge some sentence breaks for young accounts if (chance(b.runOn)) out = out.replace(/\. ([a-z])/, " $1"); // apostrophe drops: don't -> dont etc. out = out.replace(/(\w)'(t|s|m|re|ve|ll|d)\b/g, function (m, a, suf) { return chance(b.aposDrop) ? a + suf : m; }); // occasional missing space after comma if (chance(0.12)) out = out.replace(/, ([a-z])/, ",$1"); // trailing period drop if (out.charAt(out.length - 1) === "." && chance(b.dropPeriod)) out = out.slice(0, -1); return out.trim(); } /* ================= frame banks ================= {t} = topic keyword from the post, {p} = user's own point. Frames containing {t} are only used when a topic was found. */ var FRAMES = { oneliner: [ "lol {t} really said hold my beer", "nobody warned me about {t}", "the {t} lore goes deeper than i thought", "average {t} experience", "certified {t} moment", "{t} strikes again lol", "not the {t} jumpscare", "peak {t} behavior ngl", "my last two braincells watching this", "tell me this isnt scripted lol", "bro really woke up and chose {t}", "the plot armor on this one is wild", "speedran the worst possible outcome", "this is cinema", "instant regret, speedrun edition", "somewhere a manager is screaming rn", "the way i would simply log off forever", "rent free in my head now, thanks", "bold of you to post this lol", "this the kind of thing you cant unsee", "frame this. put it in a museum", "zero thoughts behind those eyes" ], relatable: [ "same thing happened to me last week", "thought i was the only one lol", "this is literally my life rn", "felt this in my soul ngl", "same. every single time", "been there, still there somehow", "why is this so accurate tho", "glad its not just me", "me every time {t} comes up", "the {t} thing gets me every time", "i swear this happens to me monthly", "nobody warned me it was this common", "ok so its not just my luck then", "this lives in my head rent free at this point", "every time i think im over it, this pops up", "my whole feed is just this now lol", "i feel seen and attacked at the same time", "story of my life basically", "the accuracy is actually scary", "glad someone finally said it" ], sawal: [ "wait how long did that take tho", "did it actually work or nah", "what did you end up doing after", "is this normal or is it just me", "how much did that run you", "wait what happened next tho", "anyone else tried this before", "does it get better or does it stay like this", "ok but how did nobody notice", "what made you try {t} in the first place", "is the {t} thing worth it or nah", "wait, people actually do this?", "how is this the first time im hearing about this", "genuinely asking, what would you do different", "did anyone warn you or you just found out the hard way", "so whats the move now", "how long did you put up with it before this", "wait, is this a regular thing or a one off" ], dry: [ "cool. another one", "shocking. nobody saw that coming", "great. just great", "imagine still being surprised by this", "and in other news, water is wet", "bold strategy. lets see how it plays out", "sure, thatll fix everything", "oh no. anyway", "peak {t} behavior", "the bar was on the floor and still", "weird how this keeps happening", "truly a mystery for the ages", "love this for everyone involved", "another day, another {t} incident", "couldnt be me. oh wait", "fascinating. anyway", "nobody could have predicted this. nobody", "the system works, clearly", "what a time to be alive", "file this under things we all saw coming" ], helpful: [ "try restarting it first, that fixed mine", "check the settings, theres a toggle for that", "had the same issue, turned out to be the cable", "update it first, then try again. worked for me", "do it in the order the manual says, trust me", "mine did that too, it was a loose connection", "give it a day, sometimes it sorts itself out", "you gotta clean it first or it keeps doing that", "the {t} part is usually the culprit", "start with the cheapest fix first, always", "mine was still under warranty, worth checking", "dont force it, theres a release for that", "switch it off, wait a full minute, back on", "that setting is buried, its under advanced", "worked on my second try, first try i messed it up", "check if theres a newer version, mine was ancient", "take a picture before you take it apart. future you says thanks", "nine times out of ten its the simplest thing" ], story: [ "same thing happened to me a while back. ignored it for like a week and it only got worse lol", "my neighbor did exactly this last summer. took him a whole weekend to undo it", "tried this last year and ngl it worked way better than i expected. still surprised tbh", "reminds me of my first apartment. same problem, zero clue what to do, just vibes", "my dad warned me about this exact thing and i still did it. he brings it up every holiday", "i learned this the hard way a few years ago. cost me more than i want to admit", "coworker of mine went through this in spring. whole office heard about it for a month", "first time it happened i panicked and called my brother at like midnight. he still teases me about it", "my grandma had a fix for this that made no sense and somehow worked every single time", "went down this rabbit hole a couple years ago. came out the other side with opinions nobody asked for", "same story at my old job. different people, exact same ending", "i put this off for months thinking it would fix itself. reader, it did not", "my roommate did this in college and we still tell the story like it was a major event", "took me three tries to get this right. first two were a disaster, third one clicked" ], generic: [ "lol this is so real", "wait really?? that actually happened", "same here ngl", "this happens way too much", "cant make this stuff up", "every single time", "no way lmao", "felt that", "so true tho", "the fact that this keeps happening is wild", "nobody talks about this enough tbh", "seen this exact thing play out like three times now", "its always the same story with this stuff", "this is the most reddit thing ive seen today", "cant even be mad, thats impressive", "nobody is ready for this conversation" ] }; /* frames that carry the user's own point */ var POINT_FRAMES = [ "ngl {p}", "tbh {p}", "fr {p}", "{p}, simple as that", "this. {p}", "{p} lol happens every time", "{p} and thats just how it goes", "lowkey {p}", "honestly {p}, cant argue with that", "{p}. every single time", "same, {p}", "{p} tho", "yeah no, {p}", "{p} and nobody talks about it", "ok but {p}", "{p}, been saying this", "real talk, {p}", "{p}. end of story", "unpopular maybe but {p}", "{p} and its not even close" ]; var POINT_FRAMES_SHORT = [ "lol {p}", "{p} lol", "wait {p}??", "same, {p}", "fr {p}", "ngl {p}", "{p} fr", "this, {p}" ]; /* tone nudges */ var TONE_OPENERS = { agree: ["this.", "exactly.", "fr,", "100%.", "yep.", "hard agree."], funny: ["lol", "lmao", "ok but", "nah cuz"], casual: ["ngl", "tbh", "honestly", "lowkey"], question: [], helpful: [] }; var TONE_CLOSERS = { funny: ["lol", "lmao", "im dead", "no bc why is this actually funny"], question: ["or is it just me?", "anyone else?", "or nah?", "am i wrong?", "just me?"], helpful: ["worked for me", "try that first", "thats what fixed mine"], agree: [], casual: [] }; /* ================= session memory: no repeats ================= */ var usedFrames = {}; // style|band -> {frameText: true} var usedOpeners = {}; // first-3-words -> true var lastOutput = ""; function pickFresh(pool, key) { if (!usedFrames[key]) usedFrames[key] = {}; var fresh = []; for (var i = 0; i < pool.length; i++) if (!usedFrames[key][pool[i]]) fresh.push(pool[i]); if (!fresh.length) { usedFrames[key] = {}; fresh = pool.slice(); } var f = pick(fresh); usedFrames[key][f] = true; return f; } /* ================= topic / point extraction ================= */ var STOPWORDS = {}; ("the a an and or but of to in on for with my me i you your yours is are was were it its this that what when how why do does did will would can cant should about from into just really very has have had been being am if so as at by be we they he she his her their our us not no yes get got one two all any anyone someone people thing things way while down up out over after before again still even ever much many more most other others put make made go going want know think feel like who whom which there here then than too").split(" ").forEach(function (w) { STOPWORDS[w] = 1; }); function extractTopic(post) { if (!post) return null; var words = post.toLowerCase().replace(/[^a-z0-9'\s]/g, " ").split(/\s+/); var content = []; for (var i = 0; i < words.length; i++) { var w = words[i].replace(/^'+|'+$/g, ""); if (w.length >= 4 && !STOPWORDS[w]) content.push(w); } return content.length ? content[0] : null; } var URDU_MAP = { bohat: "really", bahut: "really", buhat: "really", boht: "really", acha: "good", accha: "good", sahi: "true", bilkul: "totally", mujhe: "me", mujehy: "me", mujy: "me", mera: "my", mere: "my", meri: "my", tum: "you", apka: "your", ye: "this", yeh: "this", wo: "that", hai: "is", hain: "are", nahi: "not", nai: "not", lekin: "but", aur: "and", bhi: "also", kya: "what", kesa: "how", kaisa: "how", jab: "when", tha: "was", thi: "was", gaya: "went", hota: "happens", hua: "happened", chahiye: "need", log: "people", banda: "guy", krna: "do", karna: "do", es: "this", is: "this", us: "that", asal: "", asalmein: "", asal_mein: "", pr: "on", par: "on", mein: "in", se: "from", ka: "of", ki: "of", ke: "of", din: "days", agr: "if", agar: "if", phir: "then", ab: "now", kabhi: "ever" }; function cleanPoint(raw) { if (!raw) return ""; var words = raw.trim().replace(/\s+/g, " ").split(" "); var out = []; for (var i = 0; i < words.length; i++) { var raw_w = words[i]; var key = raw_w.toLowerCase().replace(/[^a-z]/g, ""); var mapped = URDU_MAP[key]; if (mapped === "") continue; else if (mapped) out.push(mapped); else if (/^[a-zA-Z0-9'.,!?]+$/.test(raw_w)) out.push(raw_w.replace(/[.!?]+$/, "")); else out.push(raw_w); } var p = out.join(" ").replace(/\s{2,}/g, " ").replace(/\s+([,.!?])/g, "$1").trim(); p = p.replace(/^(matlab|mtlb)\s+/i, ""); return p; } /* ================= word trimming ================= */ var TRAILING_STOP = { the: 1, a: 1, an: 1, and: 1, or: 1, but: 1, to: 1, of: 1, in: 1, on: 1, so: 1, with: 1, for: 1, just: 1 }; function trimToWords(text, max) { var words = text.split(/\s+/); if (words.length <= max) return text; words = words.slice(0, max); var last = words[words.length - 1].toLowerCase().replace(/[^a-z']/g, ""); while (words.length > 3 && TRAILING_STOP[last]) { words.pop(); last = words[words.length - 1].toLowerCase().replace(/[^a-z']/g, ""); } return words.join(" ").replace(/[.,;:]+$/, ""); } function padShort(text, band) { var pads = ["lol", "ngl", "fr", "tho", "same", "real"]; for (var i = pads.length - 1; i > 0; i--) { var j = rnd(i + 1), tmp = pads[i]; pads[i] = pads[j]; pads[j] = tmp; } for (var k = 0; k < pads.length && wordCount(text) < EB(band).min; k++) { var words = text.toLowerCase().split(/\s+/); if (words.indexOf(pads[k]) === -1) text = text + " " + pads[k]; } return text; } function fillUp(text, band) { var isDetail = (typeof state !== "undefined" && state.lengthSel === "detail"); if (band <= 2 && !isDetail) return padShort(text, band); if (band <= 2 && isDetail) { var t2 = 0; while (wordCount(text) < EB(band).min && t2 < 3) { text = text.replace(/[.!?]+$/, "") + ". " + pickFresh(ADDONS, "addon"); t2++; } return text; } var tries = 0; var maxTries = isDetail ? 10 : 3; while (wordCount(text) < EB(band).min && tries < maxTries) { var add = isDetail ? pickFresh(DETAIL_BEATS.concat(ADDONS), "detailbeat") : pickFresh(ADDONS, "addon"); text = text.replace(/[.!?]+$/, "") + ". " + add; tries++; } return text; } var ADDONS = [ "happens more than people think", "seen it play out a few times now", "and it keeps happening", "nobody learns the first time", "the pattern never changes", "still gets me every time", "wish i was exaggerating", "happens in every thread like this", "seen the exact same thing twice this month" ]; /* ================= reply banks (Mode 3) ================= */ var REPLY = { agree: [ "this. people really sleep on that part", "exactly what i was gonna say lol", "same, saw it happen like twice this month", "fr, and nobody wants to admit it", "yep. learned that one the hard way", "this is the part people always skip", "hard agree, esp the last bit", "same experience here, almost word for word", "been saying this. nobody listens lol", "real. wish more people got this", "thats literally what happened at my place", "100%, the {t} part especially", "yeah the {t} thing is so real", "glad someone said it, the {t} bit is spot on", "the {t} point is the one nobody makes", "came here to say this and you beat me to it", "underrated take honestly", "this is the answer right here" ], disagree: [ "idk man, that hasnt been my experience at all", "ehh, depends. mine went the complete opposite way", "nah i gotta disagree on this one", "see i thought that too, then i actually tried it", "thats true for some people maybe, not in my case", "idk, the {t} part is where you lost me", "counterpoint: it also fails like half the time", "sure, until it doesnt lol", "i mean... kinda? not really tho", "thats a stretch ngl", "worked for you maybe. disaster for me", "yeah no, hard pass on that take", "people keep saying this and it keeps not being true", "eh, the {t} thing specifically doesnt hold up", "idk about all that. seen it go sideways too many times", "strong disagree from me, and i wanted it to be true", "thats only half the story tho", "in theory sure. in practice, not once" ], correctFact: [ "small thing, its actually {f}", "close, but its {f}, not that", "pretty sure its {f} actually", "fun fact nobody asked for: {f}", "i used to think the same, turns out its {f}", "{f}, actually. common mixup tho", "minor correction, {f}", "nah its {f}. only know cuz i messed it up once myself", "its {f} btw", "tiny detail but {f}", "i made this exact mistake last year, its {f}" ], correctQ: [ "you sure about that? i always heard the opposite", "huh, pretty sure thats not right tho", "wait is that actually true? never heard that version", "idk, ive always seen it the other way around", "genuinely asking, where did you read that", "hmm, not saying youre wrong but thats news to me", "that sounds off ngl, the {t} part at least", "wait, since when? the {t} thing i mean", "you got a source for that? feels off", "ehh im not fully sold on that one" ], simple: [ "lol fair enough", "ha, ok thats a take", "noted lol", "oh man, this thread", "well now im invested", "this comment section did not disappoint", "ok i laughed at this one", "the timing of this post lol", "saving this thread for later", "and here i thought today would be boring", "this is the content i open this app for", "somehow this made my day worse and better", "wild that this is free entertainment", "ok this one sent me" ], sawalBack: [ "wait, how did that even start tho", "ok but what happened after that", "how long did the {t} thing go on for", "wait, so what did you do next", "genuinely curious, was the {t} part planned or just luck", "hold on, back up. how did we get here", "what was the first sign something was off", "did anyone else see it or just you", "ok i need the full story on this one", "how often does the {t} thing happen tho", "and then what, you just left it like that?", "wait why tho, actually asking" ], dryExtra: [ "cool story tho", "if you say so", "mmhmm", "alright then", "sure jan", "fascinating stuff" ] }; /* ================= assemble engine ================= */ function fillSlots(frame, slots) { var out = frame; if (slots.topic) out = out.split("{t}").join(slots.topic); if (slots.point) out = out.split("{p}").join(slots.point); if (slots.fact) out = out.split("{f}").join(slots.fact); if (slots.detail) out = out.split("{d}").join(slots.detail); return out; } function openerKey(text) { return text.toLowerCase().split(/\s+/).slice(0, 3).join(" "); } function applyTone(text, tone, band, frame) { var b = EB(band); // agree openers if (tone === "agree" && chance(0.5) && !/^(this|exactly|fr|yep|100%)/i.test(text)) { var op = pick(TONE_OPENERS.agree); if (wordCount(text) + 2 <= b.max) text = op + " " + text; } if ((tone === "funny" || tone === "casual") && chance(0.3)) { var op2 = pick(TONE_OPENERS[tone]); if (text.toLowerCase().indexOf(op2.replace(/[^a-z]/g, "")) !== 0 && wordCount(text) + 1 <= b.max) { text = op2 + " " + text; } } // closers if (tone === "funny" && chance(0.4) && !/lol|lmao/.test(text)) { var c1 = pick(TONE_CLOSERS.funny); if (wordCount(text) + wordCount(c1) <= b.max) text = text.replace(/[.]$/, "") + " " + c1; } if (tone === "question" && text.indexOf("?") === -1 && chance(0.65)) { var c2 = pick(TONE_CLOSERS.question); if (wordCount(text) + wordCount(c2) <= b.max) text = text.replace(/[.]$/, "") + ", " + c2; } if (tone === "helpful" && chance(0.35) && !/worked|fixed|try/.test(text)) { var c3 = pick(TONE_CLOSERS.helpful); if (wordCount(text) + wordCount(c3) <= b.max) text = text.replace(/[.]$/, "") + ". " + c3; } return text; } function assemble(poolKey, pool, slots, band, tone) { var b = EB(band); var usable = []; for (var i = 0; i < pool.length; i++) { var f = pool[i]; if (f.indexOf("{t}") !== -1 && !slots.topic) continue; if (f.indexOf("{p}") !== -1 && !slots.point) continue; if (f.indexOf("{f}") !== -1 && !slots.fact) continue; if (f.indexOf("{d}") !== -1 && !slots.detail) continue; usable.push(f); } if (!usable.length) usable = FRAMES.generic; var result = ""; for (var attempt = 0; attempt < 6; attempt++) { var frame = pickFresh(usable, poolKey); var text = fillSlots(frame, slots); if (wordCount(text) > b.max + 4 && attempt < 4) continue; if (tone) text = applyTone(text, tone, band, frame); if (usedOpeners[openerKey(text)] && attempt < 4) continue; text = roughen(text, band); text = trimToWords(text, b.max); if (wordCount(text) < b.min) text = fillUp(text, band); if (text === lastOutput && attempt < 5) continue; usedOpeners[openerKey(text)] = true; result = text; break; } if (!result) { result = roughen(fillSlots(pick(usable), slots), band); result = trimToWords(result, b.max); } lastOutput = result; return result; } /* ================= helpers for UI ================= */ function $(id) { return document.getElementById(id); } function getRadio(name) { var el = document.querySelector('input[name="' + name + '"]:checked'); return el ? parseInt(el.value, 10) : 1; } function showOut(wrapId, textId, wordsId, bandId, text, band) { $(textId).textContent = text; $(wordsId).textContent = "words: " + wordCount(text); $(bandId).textContent = "band: " + EB(band).name + " · " + EB(band).lenLabel + " · " + EB(band).min + "–" + EB(band).max + " words"; $(wrapId).classList.add("show"); } function copyText(text, btn) { function done() { var old = btn.textContent; btn.textContent = "copy ho gaya ✓"; btn.classList.add("done"); setTimeout(function () { btn.textContent = old; btn.classList.remove("done"); }, 1600); } if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(text).then(done, function () { fallback(); done(); }); } else { fallback(); done(); } function fallback() { var ta = document.createElement("textarea"); ta.value = text; ta.style.position = "fixed"; ta.style.opacity = "0"; document.body.appendChild(ta); ta.select(); try { document.execCommand("copy"); } catch (e) {} document.body.removeChild(ta); } } /* ================= MODE 1 : generate ================= */ var state = { tone: "funny", style: "oneliner", stance: "agree", repStyle: "oneliner", lengthSel: "darmiyana" }; var advisor = { op: "no", ques: "no", fresh: "no", action: "reply" }; function doGenerate() { var band = getRadio("ageGen"); var topic = extractTopic($("postInput").value); var point = cleanPoint($("pointInput").value); if (band === 1 && point) point = point.split(/\s+/).slice(0, 6).join(" "); var slots = { topic: topic, point: point, fact: "" }; var pool, key; var style = state.style; if (style === "story" && band < 3) style = "relatable"; if (point && band === 1) { pool = POINT_FRAMES_SHORT; key = "point|1"; } else if (point && chance(0.6)) { pool = POINT_FRAMES; key = "point|" + band; } else if (!topic && !point && chance(0.35)) { pool = FRAMES.generic; key = "generic|" + band; } else { pool = FRAMES[style]; key = style + "|" + band; } var text = assemble(key, pool, slots, band, state.tone); showOut("genOut", "genText", "genWords", "genBand", text, band); } /* ================= MODE 2 : humanize ================= */ var HUM_DICT = [ [/\bi believe that\b/gi, "i think"], [/\bi believe\b/gi, "i think"], [/\bin my humble opinion\b/gi, "imo"], [/\bin my opinion\b/gi, "imo"], [/\badditionally,?\s*/gi, ""], [/\bfurthermore,?\s*/gi, ""], [/\bmoreover,?\s*/gi, ""], [/\bin addition,?\s*/gi, ""], [/\bhowever,\s*/gi, "but "], [/\bhowever\b/gi, "but"], [/\btherefore,?\s*/gi, "so "], [/\bconsequently,?\s*/gi, "so "], [/\bthus,?\s*/gi, "so "], [/\bpurchased\b/gi, "bought"], [/\bpurchase\b/gi, "buy"], [/\butilize\b/gi, "use"], [/\butilise\b/gi, "use"], [/\bapproximately\b/gi, "around"], [/\bindividuals\b/gi, "people"], [/\bsufficient\b/gi, "enough"], [/\bnumerous\b/gi, "tons of"], [/\bcurrently\b/gi, "right now"], [/\bin order to\b/gi, "to"], [/\bdue to the fact that\b/gi, "because"], [/\ba large number of\b/gi, "a bunch of"], [/\bis able to\b/gi, "can"], [/\bare able to\b/gi, "can"], [/\bin the event that\b/gi, "if"], [/\bat this point in time\b/gi, "right now"], [/\bvery\b/gi, function () { return chance(0.5) ? "so" : "really"; }], [/\bextremely\b/gi, "super"], [/\bperhaps\b/gi, "maybe"] ]; function humanizeText(raw, band) { var b = EB(band); var t = " " + raw.trim().replace(/\s+/g, " ") + " "; for (var i = 0; i < HUM_DICT.length; i++) t = t.replace(HUM_DICT[i][0], HUM_DICT[i][1]); t = scrubAI(t); t = forceContractions(t); t = t.trim(); if (!t) return ""; var sentences = t.match(/[^.!?]+[.!?]+|[^.!?]+$/g) || [t]; var out = [], count = 0; for (var s = 0; s < sentences.length; s++) { var sent = sentences[s].trim(); if (!sent) continue; var w = wordCount(sent); if (w > 16) { // trim long sentence at a comma near word 13, else hard cut var words = sent.split(/\s+/); var cut = -1; for (var j = Math.min(14, words.length - 1); j > 6; j--) { if (/,$/.test(words[j])) { cut = j; break; } } if (cut > 0) sent = words.slice(0, cut + 1).join(" ").replace(/,$/, "."); else sent = words.slice(0, 15).join(" ") + "."; w = wordCount(sent); } if (count + w <= b.max || out.length === 0) { if (out.length === 0 && w > b.max) sent = trimToWords(sent, b.max); out.push(sent); count += wordCount(sent); if (count >= b.max) break; } else break; } var res = out.join(" ").replace(/\s+/g, " ").trim(); // casing: young accounts write lowercase i and lowercase starts if (band <= 2 && chance(0.6)) res = res.replace(/ I /g, " i "); if (chance(1 - EB(band).capStart)) res = res.charAt(0).toLowerCase() + res.slice(1); // light apostrophe roughening res = res.replace(/(\w)'(t|s|m|re|ve|ll|d)\b/g, function (m, a, suf) { return chance(EB(band).aposDrop * 0.6) ? a + suf : m; }); // drop final period if (res.charAt(res.length - 1) === "." && chance(EB(band).dropPeriod)) res = res.slice(0, -1); return res; } function doHumanize() { var raw = $("draftInput").value.trim(); if (!raw) { $("humNote").classList.add("show"); return; } $("humNote").classList.remove("show"); var band = getRadio("ageHum"); var text = humanizeText(raw, band); if (!text) { $("humNote").classList.add("show"); return; } showOut("humOut", "humText", "humWords", "humBand", text, band); } /* ================= MODE 3 : reply + advisor ================= */ function updateAdvisor() { var a = advisor, line, mode; if (a.op === "yes") { line = "Reply karo — OP ka comment hai, OP aksar wapas jawab deta hai, tumhara comment upar rahega."; mode = "reply"; } else if (a.ques === "yes") { line = "Reply karo — comment mein sawal pucha gaya hai, seedha usi ka jawab do, wahi sab se zyada visible hoga."; mode = "reply"; } else if (a.fresh === "yes") { line = "Fresh comment karo post par — post naya hai, early comments sab se zyada dekhe jate hain. Ajnabi ke comment ke neechay reply dab jayega."; mode = "fresh"; } else { line = "Reply karo sab se relevant comment ko — post purana hai, fresh comment neechay dab jayega, reply wahan dikhega jahan guftagu chal rahi hai."; mode = "reply"; } advisor.action = mode; $("advText").textContent = line; $("advMode").textContent = "mode: " + (mode === "fresh" ? "fresh comment (Mode 1 wala style)" : "reply"); $("repBtn").textContent = mode === "fresh" ? "Fresh comment banao" : "Reply banao"; } function doReply() { var band = getRadio("ageRep"); // advisor says fresh comment -> Mode 1 behaviour with reply-mode settings if (advisor.action === "fresh") { var topicF = extractTopic($("replyInput").value); var styleF = state.repStyle; if (styleF === "story" && band < 3) styleF = "relatable"; var poolF = topicF || chance(0.5) ? FRAMES[styleF] : FRAMES.generic; var textF = assemble("fresh|" + styleF + "|" + band, poolF, { topic: topicF, point: "", fact: "" }, band, null); showOut("repOut", "repText", "repWords", "repBand", textF, band); return; } var their = $("replyInput").value.trim(); if (!their) { $("repNote").classList.add("show"); return; } $("repNote").classList.remove("show"); var topic = extractTopic(their); var stance = state.stance; var slots = { topic: topic, point: "", fact: "" }; var pool, key; if (stance === "agree") { pool = REPLY.agree; key = "ragree|" + band; } else if (stance === "disagree") { pool = REPLY.disagree; key = "rdis|" + band; } else if (stance === "simple") { pool = REPLY.simple; key = "rsimple|" + band; } else if (stance === "sawal") { pool = REPLY.sawalBack; key = "rsawal|" + band; } else { var fact = cleanPoint($("factInput").value); if (fact) { if (band === 1) fact = fact.split(/\s+/).slice(0, 6).join(" "); slots.fact = fact; pool = REPLY.correctFact; key = "rcorr|" + band; } else { pool = REPLY.correctQ; key = "rcorrq|" + band; } } // style flavour: dry adds dry extras, sawal style asks questions back, oneliner adds funny closers if (state.repStyle === "dry" && stance !== "correct") pool = pool.concat(REPLY.dryExtra); var tone = null; if (state.repStyle === "sawal" && stance !== "sawal") tone = "question"; if (state.repStyle === "oneliner") tone = "funny"; if (state.repStyle === "story" && band >= 3 && stance === "agree" && chance(0.4)) { pool = FRAMES.story; key = "rstory|" + band; tone = null; } var text = assemble(key, pool, slots, band, tone); showOut("repOut", "repText", "repWords", "repBand", text, band); } /* ================= POORI POST smart suggest ================= */ var MIRROR = [ "the {d} part got me, not gonna lie", "its always the {d} detail that sticks with you", "the {d} thing brought back some memories ngl", "{d} is exactly the kind of detail you never forget", "that {d} detail is gonna stay with me for a while", "something about the {d} part just hits different", "the {d} bit made the whole story real for me", "i felt that {d} part in my chest a little", "its the small stuff like the {d} that stays with you", "yeah the {d} detail is the one i cant shake" ]; var OPENQ = [ "mine changes every year but lately its been the same one", "used to be one thing, now its completely different lol", "depends on the day honestly", "the boring answer? same as half the people here", "nobody believes me but mine is super specific", "for me its the simple one nobody picks", "i have thought about this way too much ngl", "the honest answer is kinda embarrassing lol", "same answer since i was like twelve, hasnt changed", "whatever it is, it finds me at the worst time" ]; var CONCRETE = {}; ("grandma grandpa grandmother grandfather mom dad mother father sister brother family kitchen coffee tea rain summer winter morning night pillow bed room house apartment garden school college office store shop car truck bike dog cat bird music song book movie food smell scent perfume lotion soap grass flowers snow beach ocean river hair hands face eyes voice laugh smile dinner lunch breakfast sunday monday holiday birthday wedding photo letter gift money job boss teacher friend friends neighbor neighbors street road town city").split(" ").forEach(function (w) { CONCRETE[w] = 1; }); function extractDetail(text, topic) { if (!text) return ""; var words = text.toLowerCase().replace(/[^a-z0-9'\s]/g, " ").split(/\s+/); var content = [], i, w; for (i = 0; i < words.length; i++) { w = words[i].replace(/^'+|'+$/g, ""); if (w.length >= 3 && !STOPWORDS[w] && content.indexOf(w) === -1) content.push(w); } for (i = 0; i < content.length; i++) if (CONCRETE[content[i]]) return content[i]; for (i = 0; i < content.length; i++) if (content[i] !== topic && content[i].length >= 4) return content[i]; return topic || ""; } function analyzePost(raw) { var low = " " + raw.toLowerCase().replace(/\s+/g, " ") + " "; var wc = wordCount(raw); var iCount = (low.match(/\bi\b/g) || []).length; if (/(what should i|how do i|how can i|any tips|any advice|advice|recommend|which one|should i buy|help me|what do i do|any suggestions|suggest me|what would you do)/.test(low)) { return { name: "Helpful jawab", style: "helpful", tone: "helpful", pool: null, reason: "post mein advice manga gaya hai — helpful jawab sab se zyada trust aur upvote deta hai." }; } if (/(unpopular opinion|hot take|am i the only one|change my mind|i think that|in my opinion|\bimo\b)/.test(low)) { return { name: "Agree + chhota sa point", style: "relatable", tone: "agree", pool: null, reason: "opinion post hai — agree ke sath halka sa apna point chhote account ke liye sab se safe rehta hai aur perform bhi karta hai." }; } if (/(lol|lmao|rofl|funniest|dumbest|stupidest|weirdest|meme)/.test(low)) { return { name: "One-liner / mazak wala", style: "oneliner", tone: "funny", pool: null, reason: "post ka mood halka aur funny hai — wahan lamba jawab nahi, ek sharp one-liner chalta hai." }; } if (/(what is your|what's your|whats your|what is a|what's a|whats a|does anyone|does anybody|how do you|how many of you|tell me a|anyone else feel|anyone else get)/.test(low)) { return { name: "Casual jawab + tiny personal touch", style: "relatable", tone: "casual", pool: "openq", reason: "ye open sawal hai poori community se — casual jawab mein halki si personal touch sab se real lagti hai." }; } if (/(today i|yesterday|last night|last week|last year|last month|this morning|when i was|growing up|my grandma|my grandpa|my grandmother|my grandfather|my mom|my dad|my mother|my father|i remember|years ago|back in \d{4})/.test(low) || (wc > 55 && iCount >= 4)) { return { name: "Relatable — story ki detail mirror karke", style: "relatable", tone: "casual", pool: "mirror", reason: "ye personal story hai — story ki ek specific detail mirror karna comment ko sab se real banata hai." }; } return { name: "Casual observation", style: "relatable", tone: "casual", pool: null, reason: "koi clear signal nahi mila — casual observation har thread mein safe rehti hai." }; } function syncChips(containerId, attr, value) { document.querySelectorAll("#" + containerId + " .chip").forEach(function (c) { c.setAttribute("aria-pressed", c.getAttribute(attr) === value ? "true" : "false"); }); } function doSuggest() { var raw = $("fullPostInput").value.trim(); var box = $("sugBox"); if (!raw) { box.innerHTML = "Suggestion: pehle upar poori post paste karo."; box.classList.add("show"); return; } var band = getRadio("ageGen"); if (hasBuyingIntent(raw)) { box.innerHTML = ""; var pb = document.createElement("b"); pb.textContent = "Suggestion: Product recommend karna best rahega — user ne khud manga hai. "; box.appendChild(pb); box.appendChild(document.createTextNode("Post mein khareedne ki baat hai, wahan normal comment ki jagah natural sa recommend zyada kaam karega.")); box.appendChild(document.createElement("br")); box.appendChild(makeProductButton(function () { openProductWith(raw); })); box.classList.add("show"); return; } var a = analyzePost(raw); var styleToShow = a.style; if (a.pool === "mirror" && band >= 3) styleToShow = "story"; state.tone = a.tone; state.style = styleToShow; syncChips("toneChips", "data-tone", a.tone); syncChips("styleChips", "data-style", styleToShow); box.innerHTML = ""; var bEl = document.createElement("b"); bEl.textContent = "Suggestion: " + a.name + " — "; box.appendChild(bEl); box.appendChild(document.createTextNode(a.reason)); box.classList.add("show"); if (a.pool) { var topic = extractTopic(raw); var detail = a.pool === "mirror" ? extractDetail(raw, topic) : ""; var poolArr = a.pool === "mirror" ? (band >= 3 ? MIRROR.concat(FRAMES.story) : MIRROR) : OPENQ; var text = assemble(a.pool + "|" + band, poolArr, { topic: topic, point: "", fact: "", detail: detail }, band, a.tone); showOut("genOut", "genText", "genWords", "genBand", text, band); } else { if (!$("postInput").value.trim()) $("postInput").value = raw.split("\n")[0].slice(0, 200); doGenerate(); } } /* ================= buying intent detection ================= */ function hasBuyingIntent(text) { if (!text) return false; var low = " " + text.toLowerCase().replace(/\s+/g, " ") + " "; return /(which (one )?(should|to) (i )?buy|which should i buy|recommend|suggest|looking for|best [a-z ]{0,30}for|worth it|should i buy|should i get|konsa loon|konsa wala|koi acha|koi achha|koi best|buy karna|lena chahiye|khareed|shopping|under \$?\d+|budget mein|any good [a-z]+ for)/.test(low); } function makeProductButton(onClick) { var btn = document.createElement("button"); btn.className = "sugbtn"; btn.textContent = "Product mode mein kholo"; btn.addEventListener("click", onClick); return btn; } function openProductWith(contextText) { if (contextText) $("prodContext").value = contextText.slice(0, 600); activateTab(3); window.scrollTo({ top: 0, behavior: "smooth" }); } function checkReplyBuyingIntent() { var their = $("replyInput").value.trim(); var box = $("repSugBox"); if (hasBuyingIntent(their)) { box.innerHTML = ""; var b = document.createElement("b"); b.textContent = "Suggestion: Product recommend karna best rahega — user ne khud manga hai. "; box.appendChild(b); box.appendChild(document.createTextNode("Is comment ka seedha jawab ek natural sa recommend hai, normal reply se zyada kaam karega.")); box.appendChild(document.createElement("br")); box.appendChild(makeProductButton(function () { openProductWith(their); })); box.classList.add("show"); } else { box.classList.remove("show"); box.innerHTML = ""; } } /* ================= MODE 4 : product recommend ================= */ var PROD_TIPS = [ "Product ka naam pehle jumlay mein kabhi mat lao — pehle maslay ki baat karo.", "Ek chhoti kami zaroor batao, warna seedha ad lagta hai.", "Jawab pehle, product baad mein — yehi asli Reddit ka tareeqa hai.", "Jo cheez khud use nahi ki, us ka dawa mat karo — 'mere pas hai' wali energy rakho.", "Link sirf akhir mein, saada sa. Beech mein link ghusana sab se bara red flag hai.", "Ek hi wajah gehri batao, paanch features ki list kabhi mat banao.", "Price ya hype wale words (best ever, must buy) kabhi nahi — normal banda aise nahi bolta." ]; var PROD_PROBLEM = [ "i had the exact same problem a while back, drove me up the wall honestly", "same thing used to happen to me, became an everyday headache at some point", "went through this myself, took me forever to figure out what actually works", "this one got me for months, sounds like a small thing but it really wears you down" ]; var PROD_PROBLEM_SHORT = [ "had the same problem myself", "same thing happened to me", "dealt with this too" ]; var PROD_INTRO = [ "then a friend put me onto the {prod} and i gave it a shot", "ended up getting the {prod} after way too much comparing", "my cousin had the {prod}, tried his and just got my own after that", "after reading way too many threads i landed on the {prod}" ]; var PROD_INTRO_SHORT = [ "tried the {prod} after that", "ended up with the {prod}", "got the {prod} in the end" ]; var PROD_REASON = [ "biggest thing for me was the difference showed up in the first week of daily use, wasnt subtle", "quality turned out better than i expected at this price, and i had low expectations tbh", "its simple to use, no fiddly setup or anything like that", "mine is still going fine after all this time, no real issues so far", "it just does the one job i needed without a bunch of extra stuff getting in the way" ]; var PROD_REASON_SHORT = [ "does the job without any fuss", "quality was fine for the price", "noticed a difference pretty quick" ]; var PROD_DOWN = [ "only real downside is it runs a bit pricey, not gonna lie", "one thing though, it takes a few days to get used to at first", "my one complaint is the size, its a bit bulky if space is tight", "small downside, it goes out of stock a lot so its not always easy to grab", "only gripe from me is the battery could be better, rest is solid" ]; var PROD_DOWN_SHORT = [ "only downside, its a bit pricey", "one gripe, its kinda bulky", "only thing, its hard to find sometimes" ]; var PROD_DETAIL_EXTRA = [ "i tried the cheap option first and it didnt even last two weeks, learned my lesson about buying twice", "even people around me noticed the difference, which never happens with this kind of thing", "its just part of my routine now, feels weird on the days i dont use it" ]; function doProduct() { var prodRaw = $("prodName").value.trim(); if (!prodRaw) { $("prodNote").classList.add("show"); return; } $("prodNote").classList.remove("show"); var band = getRadio("ageProd"); var eb = EB(band); var prod = cleanPoint(prodRaw) || prodRaw; var ctx = cleanPoint($("prodContext").value); var shortMode = band <= 2 || state.lengthSel === "chhota"; if (band === 1) { var condensed = "had the same issue, got the " + prod + " and it sorted it. only downside, bit pricey"; var ctext = scrubAI(roughen(condensed, band)); var clink = $("prodLink").value.trim(); if (clink) ctext = ctext + "\nye wala hai: " + clink; var cguide = $("prodGuide"); cguide.textContent = "Tip: " + pickFresh(PROD_TIPS, "prodtips"); cguide.classList.add("show"); showOut("prodOut", "prodText", "prodWords", "prodBand", ctext, band); return; } var parts = []; var prob = shortMode ? pickFresh(PROD_PROBLEM_SHORT, "prodprobS") : pickFresh(PROD_PROBLEM, "prodprob"); parts.push(prob); var intro = shortMode ? pickFresh(PROD_INTRO_SHORT, "prodintroS") : pickFresh(PROD_INTRO, "prodintro"); parts.push(intro.split("{prod}").join(prod)); parts.push(shortMode ? pickFresh(PROD_REASON_SHORT, "prodreasS") : pickFresh(PROD_REASON, "prodreas")); if (band >= 3 && state.lengthSel === "detail") parts.push(pickFresh(PROD_DETAIL_EXTRA, "prodextra")); var downPart = shortMode ? pickFresh(PROD_DOWN_SHORT, "proddownS") : pickFresh(PROD_DOWN, "proddown"); var bodyText = roughen(parts.join(". "), band); var downText = roughen(downPart, band); var text = bodyText + ". " + downText; // keep within cap but never cut the downside — trim the body instead if (wordCount(text) > eb.max) { var room = Math.max(4, eb.max - wordCount(downText) - 1); bodyText = trimToWords(bodyText, room); text = bodyText + ". " + downText; } if (wordCount(text) < eb.min && band >= 3) { // pad before the downside so the kami hamesha akhir mein rahe var padded = fillUp(bodyText, band); text = padded + ". " + downText; if (wordCount(text) > eb.max) text = trimToWords(padded, Math.max(4, eb.max - wordCount(downText) - 1)) + ". " + downText; } text = scrubAI(text); var link = $("prodLink").value.trim(); if (link) text = text + "\nye wala hai: " + link; // rotating guidance tip var guide = $("prodGuide"); guide.textContent = "Tip: " + pickFresh(PROD_TIPS, "prodtips"); guide.classList.add("show"); showOut("prodOut", "prodText", "prodWords", "prodBand", text, band); } /* ================= wiring ================= */ var TABS = []; function activateTab(idx) { TABS.forEach(function (o, i) { o.btn.setAttribute("aria-selected", i === idx ? "true" : "false"); o.panel.classList.toggle("panel-hide", i !== idx); }); } function setupTabs() { TABS = [ { btn: $("tabGen"), panel: $("panelGen") }, { btn: $("tabHum"), panel: $("panelHum") }, { btn: $("tabRep"), panel: $("panelRep") }, { btn: $("tabProd"), panel: $("panelProd") } ]; TABS.forEach(function (t, i) { t.btn.addEventListener("click", function () { activateTab(i); }); }); } function setupAgeGroup(containerId, onChange) { var box = $(containerId); var cards = box.querySelectorAll(".agecard"); cards.forEach(function (card) { card.addEventListener("click", function () { cards.forEach(function (c) { c.classList.remove("sel"); }); card.classList.add("sel"); var input = card.querySelector("input"); if (input) input.checked = true; if (onChange) onChange(); }); }); } function setupChips(containerId, attr, onPick) { var box = $(containerId); var chips = box.querySelectorAll(".chip"); chips.forEach(function (chip) { chip.addEventListener("click", function () { chips.forEach(function (c) { c.setAttribute("aria-pressed", "false"); }); chip.setAttribute("aria-pressed", "true"); onPick(chip.getAttribute(attr)); }); }); } function refreshStoryLocks() { var genBand = getRadio("ageGen"); var repBand = getRadio("ageRep"); var genStory = document.querySelector('#styleChips .chip[data-style="story"]'); var repStory = document.querySelector('#styleChipsRep .chip[data-style="story"]'); if (genStory) genStory.classList.toggle("locked", genBand < 3); if (repStory) repStory.classList.toggle("locked", repBand < 3); if (genBand < 3 && state.style === "story") { state.style = "relatable"; document.querySelectorAll("#styleChips .chip").forEach(function (c) { c.setAttribute("aria-pressed", c.getAttribute("data-style") === "relatable" ? "true" : "false"); }); $("storyNote").classList.add("show"); setTimeout(function () { $("storyNote").classList.remove("show"); }, 3500); } if (repBand < 3 && state.repStyle === "story") { state.repStyle = "relatable"; document.querySelectorAll("#styleChipsRep .chip").forEach(function (c) { c.setAttribute("aria-pressed", c.getAttribute("data-style") === "relatable" ? "true" : "false"); }); $("storyNoteRep").classList.add("show"); setTimeout(function () { $("storyNoteRep").classList.remove("show"); }, 3500); } } function updateLambaiHints() { var map = [ ["lambaiHintGen", "ageGen"], ["lambaiHintHum", "ageHum"], ["lambaiHintRep", "ageRep"], ["lambaiHintProd", "ageProd"] ]; map.forEach(function (pair) { var el = $(pair[0]); if (!el) return; var band = getRadio(pair[1]); var eb = EB(band); var extra = ""; if (state.lengthSel === "detail" && band === 4) extra = " — Detail wala purane account par 4–6 lines, chhoti story + specific observation ke sath."; else if (state.lengthSel === "detail" && band === 1) extra = " — naya account Detail par bhi bohat short rahega, age ki realism pehle hai."; else if (state.lengthSel === "detail" && band === 2) extra = " — zyada se zyada ~3 short lines."; el.textContent = "Is age + " + eb.lenLabel + " par takreeban " + eb.min + "–" + eb.max + " words ayenge" + extra; }); // sync all lambai chip groups document.querySelectorAll(".lambaiChips .chip").forEach(function (c) { c.setAttribute("aria-pressed", c.getAttribute("data-len") === state.lengthSel ? "true" : "false"); }); } function setupLambai() { document.querySelectorAll(".lambaiChips .chip").forEach(function (chip) { chip.addEventListener("click", function () { state.lengthSel = chip.getAttribute("data-len"); updateLambaiHints(); }); }); } function init() { setupTabs(); setupLambai(); setupAgeGroup("ageGen", function () { refreshStoryLocks(); updateLambaiHints(); }); setupAgeGroup("ageHum", updateLambaiHints); setupAgeGroup("ageRep", function () { refreshStoryLocks(); updateLambaiHints(); }); setupAgeGroup("ageProd", updateLambaiHints); setupChips("toneChips", "data-tone", function (v) { state.tone = v; }); setupChips("styleChips", "data-style", function (v) { if (v === "story" && getRadio("ageGen") < 3) { $("storyNote").classList.add("show"); setTimeout(function () { $("storyNote").classList.remove("show"); }, 3500); return; } state.style = v; }); setupChips("styleChipsRep", "data-style", function (v) { if (v === "story" && getRadio("ageRep") < 3) { $("storyNoteRep").classList.add("show"); setTimeout(function () { $("storyNoteRep").classList.remove("show"); }, 3500); // revert visual selection to current style document.querySelectorAll("#styleChipsRep .chip").forEach(function (c) { c.setAttribute("aria-pressed", c.getAttribute("data-style") === state.repStyle ? "true" : "false"); }); return; } state.repStyle = v; }); setupChips("stanceChips", "data-stance", function (v) { state.stance = v; $("factField").style.display = v === "correct" ? "block" : "none"; }); // story chip click in gen when locked-but-not-selected: setupChips already marked it pressed before onPick; // fix visual state if story rejected in gen panel: document.querySelector('#styleChips .chip[data-style="story"]').addEventListener("click", function () { if (getRadio("ageGen") < 3) { document.querySelectorAll("#styleChips .chip").forEach(function (c) { c.setAttribute("aria-pressed", c.getAttribute("data-style") === state.style ? "true" : "false"); }); } }); // advisor toggles document.querySelectorAll(".chip.adv").forEach(function (chip) { chip.addEventListener("click", function () { var q = chip.getAttribute("data-q"); advisor[q] = chip.getAttribute("data-v"); document.querySelectorAll('.chip.adv[data-q="' + q + '"]').forEach(function (c) { c.setAttribute("aria-pressed", c === chip ? "true" : "false"); }); updateAdvisor(); }); }); $("genBtn").addEventListener("click", doGenerate); $("suggestBtn").addEventListener("click", doSuggest); $("regenBtn").addEventListener("click", doGenerate); $("genCopy").addEventListener("click", function () { copyText($("genText").textContent, this); }); $("humBtn").addEventListener("click", doHumanize); $("humAgain").addEventListener("click", doHumanize); $("humCopy").addEventListener("click", function () { copyText($("humText").textContent, this); }); $("repBtn").addEventListener("click", doReply); $("repRegen").addEventListener("click", doReply); $("repCopy").addEventListener("click", function () { copyText($("repText").textContent, this); }); $("prodBtn").addEventListener("click", doProduct); $("prodRegen").addEventListener("click", doProduct); $("prodCopy").addEventListener("click", function () { copyText($("prodText").textContent, this); }); $("replyInput").addEventListener("input", checkReplyBuyingIntent); $("fullPostInput").addEventListener("input", function () { var raw = $("fullPostInput").value.trim(); if (raw && hasBuyingIntent(raw)) { /* suggest button par click par product suggestion ayega */ } }); updateAdvisor(); refreshStoryLocks(); updateLambaiHints(); } init();