Last active
February 8, 2021 20:07
-
-
Save porglezomp/4908b3a3ec81139cc50d718db9566c3c to your computer and use it in GitHub Desktop.
Animal Crossing User Script (see https://twitter.com/jamchamb_/status/1025977659522789376)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Animal Crossing Twitter Rating | |
// @description Display the rating of tweets using the Animal Crossing letter rating system | |
// @version 1 | |
// @grant none | |
// @include https://twitter.com/* | |
// ==/UserScript== | |
// Notes via https://twitter.com/jamchamb_/status/1025977659522789376 | |
// As soon as you drop off a letter at the post office it's given a score. | |
// The score is determined by a series of 7 different checks, labeled A through G. | |
function computeScore(msg) { | |
// A: Checks for punctuation at the end of sentences, and capital letters. | |
// A '.', '?', or '!' symbol at the end of the letter grants 20 points. | |
// After that, every punctuation mark must be followed by a capital letter within 3 spaces (+10 or -10 each occurrence) | |
function A(msg) { | |
let score = /[.?!]\s*$/.test(msg) ? 20 : 0; | |
while (msg !== "") { | |
if (/^[.!?](.|\n){0,2}[A-Z]/.test(msg)) { | |
score += 10; | |
} else if (/^[.!?][^A-Z]{3}/.test(msg)) { | |
score -= 10; | |
} | |
msg = msg.substring(1); | |
} | |
return score; | |
} | |
// B: Checks the beginning of each word for common trigrams, using this lookup table: | |
// https://github.com/jamchamb/ac-letter-score/blob/master/trigram_table.txt | |
// The total number of trigram hits is multiplied by 3 and added to the score. | |
function B(msg) { | |
return (msg.match(TRIGRAM_REGEX) || []).length * 3; | |
} | |
// C: This checks for the first (non-space) character in the letter. | |
// If it's a capital letter, gives +20 points. If not, -10 points. | |
function C(msg) { | |
if (/^\s*[A-Z]/.test(msg)) { | |
return 20; | |
} else { | |
return -10; | |
} | |
} | |
// D: If a letter of the alphabet is repeated three times in a row (e.g. REEE), deducts 50 points and stops checking. | |
// Otherwise it does not affect the score. | |
function D(msg) { | |
if (/([A-Za-z])\1\1/.test(msg)) { | |
return -50; | |
} else { | |
return 0; | |
} | |
} | |
// E: Checks ratio of spaces to non-spaces in the letter. | |
// If it's all spaces, or (n_spaces * 100 / n_other) is less than 20, gives -20 points. | |
// Otherwise, +20 points. | |
function E(msg) { | |
if (msg.trim() === "") { | |
return -20; | |
} | |
const num_spaces = (msg.match(/\s/g) || []).length; | |
const num_other = msg.length - num_spaces; | |
if (num_spaces * 100 / num_other < 20) { | |
return -20; | |
} else { | |
return 20; | |
} | |
} | |
// F: If the letter is more than 75 characters long and goes on for at least 75 characters without | |
// any punctuation (., ?, !), it deducts 150 points! | |
function F(msg) { | |
if (msg.length > 75 && /[^.?!]{75}/.test(msg)) { | |
return -150; | |
} else { | |
return 0; | |
} | |
} | |
// G: Checks each group of 32 characters for at least one space. | |
// Deducts 20 points for each group that doesn't have one. | |
function G(msg) { | |
const chunks = msg.match(/(.|\n){32}/g) || []; | |
return chunks.map(x => /\s/.test(x) ? 0 : -20).reduce((x, y) => x + y, 0); | |
} | |
const a = A(msg); | |
const b = B(msg); | |
const c = C(msg); | |
const d = D(msg); | |
const e = E(msg); | |
const f = F(msg); | |
const g = G(msg); | |
// console.log(msg, {a, b, c, d, e, f, g}); | |
return a + b + c + d + e + f + g; | |
} | |
// We can display this on tweets! | |
function updateScoreOnTweet(tweetElem) { | |
// We've already scored this tweet, early return | |
if ('data-ac-score' in tweetElem.attributes) { | |
return; | |
} | |
// See if we can get the text element of the tweet | |
const tweetTextElem = tweetElem.querySelector('.tweet-text'); | |
if (!tweetTextElem) { | |
return; | |
} | |
// Extract the tweet text. We should probably do extra filtering for links and things? | |
const text = tweetTextElem.innerText; | |
// We compute the score from the tweet text and cache it. | |
const score = computeScore(text); | |
tweetElem.attributes['data-ac-score'] = score; | |
// Stick the score on the tweet | |
const scoreElem = getScoreElem(tweetElem); | |
if (!scoreElem) { | |
return; | |
} | |
scoreElem.querySelector('.ProfileTweet-actionCountForPresentation').innerText = score; | |
} | |
function getScoreElem(tweetElem) { | |
const res = tweetElem.querySelector('.ProfileTweet-action.ProfileTweet-action--acpoints'); | |
if (res) { | |
return res; | |
} | |
const fav = tweetElem.querySelector('.ProfileTweet-action.ProfileTweet-action--favorite'); | |
if (!fav) { | |
return null; | |
} | |
fav.insertAdjacentHTML('afterend', | |
`<div class="ProfileTweet-action ProfileTweet-action--acpoints"> | |
<div class="ProfileTweet-actionButton"> | |
<div class="IconContainer js-tooltip" data-original-title="Animal Crossing Score"> | |
<span role="presentation" class="Icon Icon--clock Icon--crescent"></span> | |
<span class="u-hiddenVisually">Animal Crossing Score</span> | |
</div> | |
<span class="ProfileTweet-actionCount" data-tweet-stat-count="0"> | |
<span class="ProfileTweet-actionCountForPresentation" aria-hidden="true">0</span> | |
</span> | |
</div> | |
</div>`); | |
return tweetElem.querySelector('.ProfileTweet-action.ProfileTweet-action--acpoints'); | |
} | |
TRIGRAM_REGEX = /\b(abl|abo|abr|abs|acc|ach|acr|act|add|adm|adv|aer|aff|afr|aft|aga|age|ago|ahe|air|ali|all|alm|alo|alr|als|alt|alw|am|ame|amo|and|ang|ani|ano|ans|any|apa|app|apr|are|arg|arm|arr|art|asi|ask|asl|ate|atm|att|aud|aug|aut|ave|avo|awa|cak|cal|cam|can|cap|car|cas|cat|cau|cen|cer|cha|che|chi|cho|chi|chu|cir|cit|cla|cle|cli|clo|coa|cof|coi|col|com|con|coo|cop|cor|cos|cou|cov|cow|cre|cri|cro|cry|cup|cur|cus|cut|bab|bac|bad|bag|bal|ban|bas|bat|be|bea|bec|bed|bee|bef|beg|beh|bel|bes|bet|bey|bic|big|bik|bil|bir|bit|bla|ble|blo|blu|boa|bod|bon|boo|borbot|bou|box|boy|bra|bre|bri|bro|bui|bur|bus|but|buy|by|eac|ear|eas|eat|edu|eff|egg|eig|eit|ele|els|emp|end|ene|eng|enj|eno|ent|equ|err|esp|eur|eve|exa|exc|exe|exp|eye|dad|dai|dam|dan|dar|dat|dau|day|dea|dec|dee|def|deg|del|dem|den|dep|des|det|dev|dic|did|die|dif|dig|din|dir|dis|div|do|doc|doe|dog|dol|don|doo|dou|dow|doz|dra|dre|dri|dro|dru|dry|due|dur|dus|dut|gai|gam|gar|gas|gat|gav|gen|ger|get|gir|giv|gla|go|god|goi|gon|goo|got|gov|gra|gre|gro|gua|gue|gui|gun|fac|fai|fal|fam|far|fas|fat|fea|feb|fed|fee|fel|few|fie|fif|fig|fil|fin|fir|fis|fiv|fix|fla|fle|fli|flo|fly|fol|foo|for|fou|fra|fre|fri|fro|fru|ful|fun|fut|i|ice|ide|if|ima|imm|imp|in|inc|ind|inf|ins|int|inv|iro|is|isl|it|its|hab|had|hai|hal|han|hap|har|has|hat|hav|he|hea|hei|hel|her|hi|hid|hig|hil|him|hir|his|hit|hol|hom|hon|hop|hor|hos|hot|hou|how|hum|hun|hur|hus|kee|kep|key|kic|kil|kin|kit|kne|kni|kno|kab|kad|kai|kak|kan|kar|kas|kat|kau|kaw|kay|kaz|kea|ked|kef|keg|ken|kes|ket|kev|kib|kie|kif|kig|kik|kim|kin|kis|kit|kiv|koc|kon|koo|kos|kot|kou|kov|kow|kun|kyi|kac|kad|kag|kai|kaj|kak|kan|kap|kar|kat|kay|ke|kea|ked|kee|kem|ken|kes|ket|kid|kig|kil|kin|kis|kod|kom|kon|koo|kor|kos|kot|kou|kov|kuc|kum|kus|ky|kys|kam|kar|kat|kea|kec|kee|kei|kev|kew|kex|kic|kig|kin|ko|kob|koi|kon|koo|kor|kos|kot|kov|kow|kum|kbj|k'c|kct|kf|kff|kft|kh|kil|kka|kld|kn|knc|kne|knl|kpe|kpi|kpp|kr|kra|krd|kth|kur|kut|kve|kwn|jan|jap|job|joi|jud|jul|jum|jun|jus|qua|que|qui|pac|pag|pai|pap|par|pas|pat|pay|pea|pen|peo|per|pho|pic|pie|pin|pip|pla|ple|poc|poi|pol|poo|pop|pos|pot|pou|pow|pra|pre|pri|pro|pub|pul|pup|pur|pus|put|sad|saf|sai|sal|sam|san|sat|sav|saw|say|sce|sch|sci|sco|sea|sec|see|sel|sen|sep|ser|set|sev|sex|sha|she|shi|sho|shu|sic|sid|sig|sil|sim|sin|sis|sit|six|siz|ski|sky|sle|sli|slo|sma|sme|smi|smo|sno|so|soa|soc|sof|soi|sol|som|son|soo|sor|sou|spa|spe|spi|spo|spr|squ|sta|ste|sti|sto|str|stu|sty|sub|suc|sud|suf|sug|sum|sun|sup|sur|swa|swe|swi|swu|sys|rac|rad|rai|ran|rap|rat|rea|rec|red|ref|reg|rel|rem|rep|req|res|ret|ric|rid|rig|rin|ris|riv|roa|roc|rod|rol|roo|ros|rou|row|rul|run|rus|una|unc|und|uni|unl|unt|up|upo|us|use|usu|tab|tak|tal|tas|tau|tax|tea|tee|tel|tem|ten|ter|tes|tha|the|thi|tho|thr|thu|tic|tie|til|tim|tir|tit|to|tod|tog|tol|tom|ton|too|top|tor|tot|tou|tow|tra|tre|tri|tro|tru|try|tue|tur|tv|twe|twi|two|tyi|typ|val|var|veg|ver|vie|vil|vis|voi|vol|vot|vai|vak|val|van|var|vas|vat|vav|vay|ve|vea|ved|vee|vei|vel|ven|ver|ves|vet|vha|vhe|vhi|vho|vhy|vid|vif|vil|vin|vir|vis|vit|viv|vok|vom|von|voo|vor|vou|vri|vro|vma|yar|yea|yel|yen|yes|yet|you|zer)/gi; | |
// Constantly update the tweet scores | |
document.querySelectorAll('.tweet').forEach(updateScoreOnTweet) | |
setInterval(() => { | |
document.querySelectorAll('.tweet').forEach(updateScoreOnTweet) | |
}, 1000); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment