use crate::ctx::GenContext;
use crate::rng::Rng;
struct BallLang {
templates: &'static [&'static str],
outcomes: &'static [&'static str],
advice: &'static [&'static str],
whos: &'static [&'static str],
topics: &'static [&'static str],
risks: &'static [&'static str],
whens: &'static [&'static str],
}
const EN: BallLang = BallLang {
templates: &[
"{outcome}",
"{outcome}, but not on {when}",
"{outcome} -- {advice}",
"Ask {who}, not me",
"{who} says {outcome}",
"The {topic} says {outcome}",
"{outcome}, unless {risk}",
"Absolutely {outcome} -- {advice}",
"{outcome}. {advice}",
"Not until {when}",
"Only if {risk}",
"{outcome}. Ask again after {when}",
"Signs point to {outcome}, but {risk}",
"{who} would say {outcome}",
"{outcome}. The {topic} has spoken",
],
outcomes: &[
"yes",
"no",
"absolutely",
"never",
"most likely",
"doubtful",
"obviously",
"not a chance",
"without a doubt",
"ask again later",
"probably",
"definitely not",
"100%",
"hard no",
"maybe in another life",
"if you believe hard enough",
"only on Tuesdays",
"the stars say yes",
"your gut knows the answer",
"that's above my pay grade",
],
advice: &[
"ship it",
"revert immediately",
"sleep on it",
"trust the process",
"delete the branch",
"blame DNS",
"check the logs first",
"have you tried restarting?",
"touch grass",
"update your LinkedIn",
"git blame someone else",
"YOLO",
"but write tests first",
"deploy on Friday",
"read the docs",
],
whos: &[
"your tech lead",
"Stack Overflow",
"the intern",
"ChatGPT",
"your rubber duck",
"the on-call engineer",
"Hacker News",
"your future self",
"the CTO",
"localhost",
"the senior dev",
"Reddit",
"the compiler",
],
topics: &[
"backlog",
"sprint retro",
"standup",
"CI pipeline",
"production logs",
"Jira board",
"pull request",
"code review",
"incident report",
"architecture diagram",
"roadmap",
"burndown chart",
],
risks: &[
"the tests are flaky",
"it's a Friday",
"you haven't pushed yet",
"the demo is tomorrow",
"someone is watching",
"the linter disagrees",
"there's a merge conflict",
"you forgot to save",
"the deadline moved",
"nobody wrote tests for that",
"production is on fire",
"the CEO is in the room",
],
whens: &[
"the next sprint",
"Mercury retrograde",
"the heat death of the universe",
"lunch",
"the deploy finishes",
"someone fixes the CI",
"Q4",
"the next standup",
"you've had coffee",
"the PR gets approved",
"the weekend",
"never",
],
};
const RU: BallLang = BallLang {
templates: &[
"{outcome}",
"{outcome}, но не раньше {when}",
"{outcome} -- {advice}",
"Спроси у {who}",
"По мнению {who}: {outcome}",
"{topic} говорит: {outcome}",
"{outcome}, если только не {risk}",
"Точно {outcome} -- {advice}",
"{outcome}. {advice}",
"Не раньше {when}",
"Только если {risk}",
"{outcome}. Спроси после {when}",
"Все указывает на «{outcome}», но {risk}",
"Спроси у {who}, а не у меня",
],
outcomes: &[
"да",
"нет",
"однозначно",
"никогда",
"скорее всего",
"сомнительно",
"очевидно",
"без шансов",
"без сомнений",
"спроси позже",
"вероятно",
"точно нет",
"100%",
"жесткое нет",
"может в другой жизни",
"если очень веришь",
"только по вторникам",
"звезды говорят да",
"доверься интуиции",
],
advice: &[
"шипай",
"откатывай немедленно",
"переспи с этим",
"доверься процессу",
"удали ветку",
"вини DNS",
"сначала логи",
"пробовал перезагрузить?",
"выйди на улицу",
"обнови LinkedIn",
"git blame кого-нибудь",
"YOLO",
"но сначала тесты",
"деплой в пятницу",
"читай доки",
],
whos: &[
"тимлида",
"Stack Overflow",
"стажера",
"ChatGPT",
"резиновой уточки",
"дежурного",
"Hacker News",
"себя из будущего",
"CTO",
"сеньора",
"Reddit",
"компилятора",
],
topics: &[
"бэклог",
"ретро",
"стендап",
"CI пайплайн",
"логи прода",
"Jira",
"пулл реквест",
"код ревью",
"пост-мортем",
"роадмап",
],
risks: &[
"тесты флакают",
"сегодня пятница",
"ты еще не запушил",
"демо завтра",
"кто-то смотрит",
"линтер против",
"есть мердж конфликт",
"ты забыл сохранить",
"дедлайн сдвинулся",
"никто не писал тесты",
"прод горит",
"CEO в комнате",
],
whens: &[
"следующего спринта",
"ретроградного Меркурия",
"тепловой смерти вселенной",
"обеда",
"конца деплоя",
"починки CI",
"Q4",
"следующего стендапа",
"кофе",
"аппрува PR",
"выходных",
"никогда",
],
};
const UK: BallLang = BallLang {
templates: &[
"{outcome}",
"{outcome}, але не раніше {when}",
"{outcome} -- {advice}",
"Запитай у {who}",
"На думку {who}: {outcome}",
"{topic} каже: {outcome}",
"{outcome}, якщо тільки не {risk}",
"Точно {outcome} -- {advice}",
"{outcome}. {advice}",
"Не раніше {when}",
"Тільки якщо {risk}",
"{outcome}. Запитай після {when}",
"Все вказує на «{outcome}», але {risk}",
"Запитай у {who}, а не в мене",
],
outcomes: &[
"так",
"ні",
"однозначно",
"ніколи",
"скоріш за все",
"сумнівно",
"очевидно",
"без шансів",
"без сумнівів",
"запитай пізніше",
"ймовірно",
"точно ні",
"100%",
"жорстке ні",
"може в іншому житті",
"якщо дуже віриш",
"тільки по вівторках",
"зірки кажуть так",
"довірся інтуїції",
],
advice: &[
"шипай",
"відкочуй негайно",
"переспи з цим",
"довірся процесу",
"видали гілку",
"вини DNS",
"спочатку логи",
"пробував перезавантажити?",
"вийди на вулицю",
"онови LinkedIn",
"git blame когось",
"YOLO",
"але спочатку тести",
"деплой у п'ятницю",
"читай доки",
],
whos: &[
"тімліда",
"Stack Overflow",
"стажера",
"ChatGPT",
"гумової качечки",
"чергового",
"Hacker News",
"себе з майбутнього",
"CTO",
"сіньйора",
"Reddit",
"компілятора",
],
topics: &[
"беклог",
"ретро",
"стендап",
"CI пайплайн",
"логи проду",
"Jira",
"пул реквест",
"код рев'ю",
"пост-мортем",
"роадмап",
],
risks: &[
"тести флакають",
"сьогодні п'ятниця",
"ти ще не запушив",
"демо завтра",
"хтось дивиться",
"лінтер проти",
"є мердж конфлікт",
"ти забув зберегти",
"дедлайн посунувся",
"ніхто не писав тести",
"прод горить",
"CEO в кімнаті",
],
whens: &[
"наступного спрінту",
"ретроградного Меркурія",
"теплової смерті всесвіту",
"обіду",
"кінця деплою",
"полагодження CI",
"Q4",
"наступного стендапу",
"кави",
"апруву PR",
"вихідних",
"ніколи",
],
};
const BE: BallLang = BallLang {
templates: &[
"{outcome}",
"{outcome}, але не раней за {when}",
"{outcome} -- {advice}",
"Запытай у {who}",
"На думку {who}: {outcome}",
"{topic} кажа: {outcome}",
"{outcome}, калі толькі не {risk}",
"Дакладна {outcome} -- {advice}",
"{outcome}. {advice}",
"Не раней за {when}",
"Толькі калі {risk}",
"{outcome}. Запытай пасля {when}",
"Усё паказвае на «{outcome}», але {risk}",
"Запытай у {who}, а не ў мяне",
],
outcomes: &[
"так",
"не",
"адназначна",
"ніколі",
"хутчэй за ўсё",
"сумніўна",
"відавочна",
"без шанцаў",
"без сумневаў",
"запытай пазней",
"верагодна",
"дакладна не",
"100%",
"жорсткае не",
"можа ў іншым жыцці",
"калі вельмі верыш",
"толькі па аўторках",
"зоркі кажуць так",
"давярай інтуіцыі",
],
advice: &[
"шыпай",
"адкочвай неадкладна",
"пераспі з гэтым",
"давярай працэсу",
"выдалі галінку",
"віні DNS",
"спачатку логі",
"спрабаваў перазагрузіць?",
"выйдзі на вуліцу",
"абнаві LinkedIn",
"git blame кагосьці",
"YOLO",
"але спачатку тэсты",
"дэплой у пятніцу",
"чытай докі",
],
whos: &[
"цімліда",
"Stack Overflow",
"стажора",
"ChatGPT",
"гумовай качачкі",
"дзяжурнага",
"Hacker News",
"сябе з будучыні",
"CTO",
"сіньёра",
"Reddit",
"кампілятара",
],
topics: &[
"бэклог",
"рэтра",
"стэндап",
"CI пайплайн",
"логі проду",
"Jira",
"пул рэквест",
"код рэўю",
"пост-мортэм",
"роадмап",
],
risks: &[
"тэсты флакаюць",
"сёння пятніца",
"ты яшчэ не запушыў",
"дэма заўтра",
"хтосьці глядзіць",
"лінтэр супраць",
"ёсць мердж канфлікт",
"ты забыўся захаваць",
"дэдлайн пасунуўся",
"ніхто не пісаў тэсты",
"прод гарыць",
"CEO у пакоі",
],
whens: &[
"наступнага спрынту",
"рэтраграднага Меркурыя",
"цеплавой смерці сусвету",
"абеду",
"канца дэплою",
"палагоджання CI",
"Q4",
"наступнага стэндапу",
"кавы",
"апруву PR",
"выхадных",
"ніколі",
],
};
const SR: BallLang = BallLang {
templates: &[
"{outcome}",
"{outcome}, али не пре {when}",
"{outcome} -- {advice}",
"Питај {who}",
"По мишљењу {who}: {outcome}",
"{topic} каже: {outcome}",
"{outcome}, осим ако {risk}",
"Дефинитивно {outcome} -- {advice}",
"{outcome}. {advice}",
"Не пре {when}",
"Само ако {risk}",
"{outcome}. Питај после {when}",
"Све указује на «{outcome}», али {risk}",
"Питај {who}, не мене",
],
outcomes: &[
"да",
"не",
"апсолутно",
"никад",
"највероватније",
"сумњиво",
"очигледно",
"нема шансе",
"без сумње",
"питај касније",
"вероватно",
"дефинитивно не",
"100%",
"тврдо не",
"можда у другом животу",
"ако довољно верујеш",
"само уторком",
"звезде кажу да",
"твој осећај зна одговор",
],
advice: &[
"шипуј",
"ревертуј одмах",
"преспавај",
"веруј процесу",
"обриши грану",
"окриви DNS",
"прво логови",
"пробао си рестарт?",
"изађи напоље",
"ажурирај LinkedIn",
"git blame неког другог",
"YOLO",
"али прво тестови",
"деплој у петак",
"читај документацију",
],
whos: &[
"тех лида",
"Stack Overflow",
"приправника",
"ChatGPT",
"гумену патку",
"дежурног",
"Hacker News",
"себе из будућности",
"CTO",
"сениора",
"Reddit",
"компајлер",
],
topics: &[
"беклог",
"ретро",
"стендап",
"CI пајплајн",
"логови прода",
"Jira",
"пул реквест",
"код ревју",
"пост-мортем",
"роадмап",
],
risks: &[
"тестови су флејки",
"данас је петак",
"ниси још пушовао",
"демо је сутра",
"неко гледа",
"линтер се не слаже",
"има мерџ конфликт",
"заборавио си да сачуваш",
"рок се померио",
"нико није писао тестове",
"прод гори",
"CEO је у соби",
],
whens: &[
"следећег спринта",
"ретроградног Меркура",
"топлотне смрти универзума",
"ручка",
"краја деплоја",
"поправке CI",
"Q4",
"следећег стендапа",
"кафе",
"одобрења PR-а",
"викенда",
"никад",
],
};
const PT_BR: BallLang = BallLang {
templates: &[
"{outcome}",
"{outcome}, mas nao {when}",
"{outcome} -- {advice}",
"Pergunta pro {who}",
"{who} diz {outcome}",
"O {topic} diz {outcome}",
"{outcome}, a menos que {risk}",
"Com certeza {outcome} -- {advice}",
"{outcome}. {advice}",
"So depois de {when}",
"So se {risk}",
"{outcome}. Pergunta de novo depois de {when}",
"Tudo aponta pra {outcome}, mas {risk}",
"{who} diria {outcome}",
"{outcome}. O {topic} falou",
],
outcomes: &[
"sim",
"nao",
"com certeza",
"nunca",
"muito provavelmente",
"duvidoso",
"obvio",
"sem chance",
"sem duvida",
"pergunta depois",
"provavelmente",
"definitivamente nao",
"100%",
"nao mesmo",
"talvez em outra vida",
"se voce acreditar muito",
"so nas tercas",
"as estrelas dizem sim",
"seu instinto sabe",
"isso ta acima do meu cargo",
],
advice: &[
"shipa logo",
"reverte agora",
"dorme com isso",
"confia no processo",
"deleta a branch",
"culpa o DNS",
"olha os logs primeiro",
"ja tentou reiniciar?",
"vai tocar grama",
"atualiza o LinkedIn",
"git blame em outro",
"YOLO",
"mas escreve teste antes",
"deploya na sexta",
"le a doc",
],
whos: &[
"tech lead",
"Stack Overflow",
"estagiario",
"ChatGPT",
"patinho de borracha",
"plantonista",
"Hacker News",
"seu eu do futuro",
"CTO",
"localhost",
"dev senior",
"Reddit",
"compilador",
],
topics: &[
"backlog",
"retro do sprint",
"daily",
"pipeline de CI",
"log de prod",
"board do Jira",
"pull request",
"code review",
"post-mortem",
"roadmap",
"burndown",
],
risks: &[
"os testes sao flaky",
"e sexta-feira",
"voce ainda nao pushou",
"o demo e amanha",
"alguem ta olhando",
"o linter discorda",
"tem merge conflict",
"voce esqueceu de salvar",
"o prazo mudou",
"ninguem escreveu teste pra isso",
"prod ta pegando fogo",
"o CEO ta na sala",
],
whens: &[
"o proximo sprint",
"Mercurio retrogrado",
"a morte termica do universo",
"o almoco",
"o deploy terminar",
"alguem arrumar o CI",
"Q4",
"a proxima daily",
"voce tomar cafe",
"o PR ser aprovado",
"o fim de semana",
"nunca",
],
};
const DE: BallLang = BallLang {
templates: &[
"{outcome}",
"{outcome}, aber nicht {when}",
"{outcome} -- {advice}",
"Frag {who}, nicht mich",
"{who} sagt {outcome}",
"Das {topic} sagt {outcome}",
"{outcome}, es sei denn {risk}",
"{outcome}. {advice}",
"Nicht vor {when}",
"Nur wenn {risk}",
"{outcome}. Frag nochmal nach {when}",
"Alles deutet auf {outcome}, aber {risk}",
],
outcomes: &[
"ja",
"nein",
"absolut",
"niemals",
"hoechstwahrscheinlich",
"zweifelhaft",
"offensichtlich",
"keine Chance",
"ohne Zweifel",
"frag spaeter nochmal",
"wahrscheinlich",
"definitiv nicht",
"100%",
"hartes Nein",
"vielleicht in einem anderen Leben",
"die Sterne sagen ja",
],
advice: &[
"ship es",
"sofort reverten",
"schlaf drueber",
"vertrau dem Prozess",
"loesch den Branch",
"DNS ist schuld",
"erst die Logs checken",
"neustart versucht?",
"geh raus",
"LinkedIn updaten",
"YOLO",
"aber erst Tests schreiben",
"deploy am Freitag",
],
whos: &[
"dein Tech Lead",
"Stack Overflow",
"der Praktikant",
"ChatGPT",
"deine Gummiente",
"der Bereitschaftsdienst",
"der CTO",
"localhost",
"der Senior Dev",
"der Compiler",
],
topics: &[
"Backlog",
"Sprint Retro",
"Standup",
"CI Pipeline",
"Produktions-Logs",
"Jira Board",
"Pull Request",
"Code Review",
"Incident Report",
"Roadmap",
],
risks: &[
"die Tests sind flaky",
"es ist Freitag",
"du hast noch nicht gepusht",
"die Demo ist morgen",
"jemand guckt zu",
"der Linter ist dagegen",
"es gibt einen Merge-Konflikt",
"der Prod brennt",
"der CEO ist im Raum",
],
whens: &[
"naechsten Sprint",
"Merkur ruecklaeufig",
"Mittagspause",
"das Deploy fertig ist",
"jemand die CI fixt",
"Q4",
"den naechsten Standup",
"du Kaffee hattest",
"das Wochenende",
"nie",
],
};
const ES: BallLang = BallLang {
templates: &[
"{outcome}",
"{outcome}, pero no {when}",
"{outcome} -- {advice}",
"Preguntale a {who}, no a mi",
"{who} dice {outcome}",
"El {topic} dice {outcome}",
"{outcome}, a menos que {risk}",
"{outcome}. {advice}",
"No hasta {when}",
"Solo si {risk}",
"{outcome}. Pregunta despues de {when}",
"Todo apunta a {outcome}, pero {risk}",
],
outcomes: &[
"si",
"no",
"absolutamente",
"nunca",
"muy probable",
"dudoso",
"obvio",
"ni chance",
"sin duda",
"pregunta despues",
"probablemente",
"definitivamente no",
"100%",
"no rotundo",
"tal vez en otra vida",
"las estrellas dicen si",
],
advice: &[
"shipealo",
"revertir ya",
"consultalo con la almohada",
"confia en el proceso",
"borra el branch",
"culpa al DNS",
"primero los logs",
"probaste reiniciar?",
"sal a caminar",
"actualiza LinkedIn",
"YOLO",
"pero primero tests",
"deploy en viernes",
],
whos: &[
"tu tech lead",
"Stack Overflow",
"el pasante",
"ChatGPT",
"tu patito de goma",
"el de guardia",
"el CTO",
"localhost",
"el senior",
"Reddit",
"el compilador",
],
topics: &[
"backlog",
"retro",
"standup",
"CI pipeline",
"logs de prod",
"Jira",
"pull request",
"code review",
"post-mortem",
"roadmap",
],
risks: &[
"los tests son flaky",
"es viernes",
"no pusheaste todavia",
"el demo es manana",
"alguien esta mirando",
"el linter no esta de acuerdo",
"hay un merge conflict",
"prod esta en llamas",
"el CEO esta en la sala",
],
whens: &[
"el proximo sprint",
"Mercurio retrogrado",
"el almuerzo",
"termine el deploy",
"alguien arregle el CI",
"Q4",
"el proximo standup",
"tomes cafe",
"el fin de semana",
"nunca",
],
};
const JA: BallLang = BallLang {
templates: &[
"{outcome}",
"{outcome}、でも{when}はダメ",
"{outcome} -- {advice}",
"{who}に聞いて",
"{who}は{outcome}と言っている",
"{topic}は{outcome}と言っている",
"{outcome}、{risk}でなければ",
"{outcome}。{advice}",
"{when}まで待って",
"{risk}の場合のみ",
"{outcome}。{when}の後にもう一度聞いて",
"全てが{outcome}を示している、でも{risk}",
],
outcomes: &[
"はい",
"いいえ",
"絶対",
"絶対ない",
"おそらく",
"疑わしい",
"明らかに",
"ありえない",
"間違いなく",
"後で聞いて",
"多分",
"絶対にない",
"100%",
"断固としてノー",
"別の人生でなら",
"星がイエスと言っている",
],
advice: &[
"シップしろ",
"すぐリバート",
"一晩寝かせろ",
"プロセスを信じろ",
"ブランチを消せ",
"DNSのせいにしろ",
"まずログを見ろ",
"再起動した?",
"外に出ろ",
"LinkedInを更新しろ",
"YOLO",
"でもまずテスト",
"金曜にデプロイ",
],
whos: &[
"テックリード",
"Stack Overflow",
"インターン",
"ChatGPT",
"ラバーダック",
"オンコール担当",
"CTO",
"localhost",
"シニアエンジニア",
"Reddit",
"コンパイラ",
],
topics: &[
"バックログ",
"レトロ",
"スタンドアップ",
"CIパイプライン",
"本番ログ",
"Jiraボード",
"プルリクエスト",
"コードレビュー",
"ポストモーテム",
"ロードマップ",
],
risks: &[
"テストがフレイキー",
"金曜日",
"まだプッシュしてない",
"デモが明日",
"誰か見てる",
"リンターが反対",
"マージコンフリクトがある",
"本番が燃えてる",
"CEOがいる",
],
whens: &[
"次のスプリント",
"水星逆行",
"昼休み",
"デプロイが終わったら",
"誰かがCI直したら",
"Q4",
"次のスタンドアップ",
"コーヒー飲んだら",
"週末",
"永遠に来ない",
],
};
fn lang_for(code: &str) -> &'static BallLang {
match code {
"ru" | "bg" | "hr" | "sl" | "pl" | "cs" | "sk" => &RU,
"uk" => &UK,
"be" => &BE,
"sr" => &SR,
"pt" | "pt-br" => &PT_BR,
"de" | "de-at" | "lb" => &DE,
"es" | "mx" | "co" | "cl" | "pe" | "ec" | "uy" | "ve" => &ES,
"ja" => &JA,
_ => &EN,
}
}
fn pick<'a>(rng: &mut Rng, pool: &'a [&'a str]) -> &'a str {
pool[rng.urange(0, pool.len() - 1)]
}
fn capitalize(s: &str) -> String {
let mut c = s.chars();
match c.next() {
None => String::new(),
Some(f) => {
let mut out = String::with_capacity(s.len());
for u in f.to_uppercase() {
out.push(u);
}
out.push_str(c.as_str());
out
}
}
}
pub fn gen(ctx: &mut GenContext<'_>, buf: &mut String) {
buf.push_str(&gen_8ball_inner(ctx));
}
fn gen_8ball_inner(ctx: &mut GenContext<'_>) -> String {
let lang = if ctx.locales.len() <= 5 {
let loc = ctx.locale();
lang_for(loc.code)
} else {
&EN
};
let tpl = lang.templates[ctx.rng.urange(0, lang.templates.len() - 1)];
let mut out = String::with_capacity(tpl.len() + 40);
let mut rest = tpl;
while let Some(pos) = rest.find('{') {
out.push_str(&rest[..pos]);
rest = &rest[pos + 1..];
if let Some(end) = rest.find('}') {
let key = &rest[..end];
let replacement = match key {
"outcome" => pick(&mut ctx.rng, lang.outcomes),
"advice" => pick(&mut ctx.rng, lang.advice),
"who" => pick(&mut ctx.rng, lang.whos),
"topic" => pick(&mut ctx.rng, lang.topics),
"risk" => pick(&mut ctx.rng, lang.risks),
"when" => pick(&mut ctx.rng, lang.whens),
_ => key,
};
out.push_str(replacement);
rest = &rest[end + 1..];
} else {
out.push('{');
}
}
out.push_str(rest);
capitalize(&out)
}