Add extraction chrome plugin

master
Oystein Kristoffer Tveit 2021-05-17 00:31:21 +02:00
parent a6ec67e3af
commit a39f5919a3
19 changed files with 7355 additions and 0 deletions

View File

@ -0,0 +1,98 @@
/* ------------------------------ Chrome Stuff ------------------------------ */
const openAndSend = ({url, message, timeout, callback=() => {}}) =>
chrome.tabs.create({url: url})
.then(tab =>
setTimeout(() =>
chrome.tabs.sendMessage(tab.id, message, callback),
timeout
));
/* ----------------------------- Boolean Algebra ---------------------------- */
const openBoolean = msg =>
openAndSend({
url: "https://boolean-algebra.com",
message: {type: "bool_alg", content: msg},
timeout: 5000,
callback: (res) =>
openAndSend({
url: "pages/answer/answer.html",
message: {type: "bool_alg_ans", content: res.content},
timeout: 1000,
})
});
/* ----------------------------- Induction Proof ---------------------------- */
openInduction = msg =>
openAndSend({
url: "https://www.wolframalpha.com/input/?i=" + encodeURIComponent(msg.expression),
message: {type: "induction", content: msg},
timeout: 15000,
callback: (res) =>
openAndSend({
url: "pages/answer/answer.html",
message: {type: "induction_ans", content: res.content},
timeout: 1000,
})
});
/* ------------------------ Permutation, Combination ------------------------ */
const fac = (n) => {
let val=1;
for (let i = 2; i <= n; i++)
val = val * i;
return val;
}
const perm = (n, r) => fac(n) / fac(n - r);
const comb = (n, r) => fac(n) / (fac(n - r) * fac(r));
const openPerm = msg =>
openAndSend({
url: "pages/answer/answer.html",
message: {type: "perms_ans", content: `\\[ \\nPr{${msg.n}}{${msg.r}} = ${perm(msg.n, msg.r)} \\]`},
timeout: 1000,
});
const openComb = msg =>
openAndSend({
url: "pages/answer/answer.html",
message: {type: "combs_ans", content: `\\[ \\nCr{${msg.n}}{${msg.r}} = ${comb(msg.n, msg.r)} \\]`},
timeout: 1000,
})
/* ----------------------------- Message switch ----------------------------- */
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
console.log("Message recieved!");
console.log("Checking message type!");
switch (message.type) {
case "bool_alg":
openBoolean(message.content);
break;
case "induction":
openInduction(message.content);
break;
case "perm":
openPerm(message.content);
break;
case "comb":
openComb(message.content);
break;
default:
console.error("Couldn't recognize message!");
break;
}
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,37 @@
{
"name": "Discrete Extraction Tools",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_icon": "icon.png",
"default_popup": "pages/popup/popup.html"
},
"permissions": [
"activeTab",
"scripting",
"tabs"
],
"host_permissions": [
"https://www.boolean-algebra.com/",
"https://www.wolframalpha.com/"
],
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["https://www.boolean-algebra.com/"],
"js": ["scripts/boolean-algebra/outer.js"]
},
{
"matches": ["https://www.wolframalpha.com/*"],
"js": ["scripts/induction/outer.js"]
}
],
"web_accessible_resources": [
{
"matches": ["<all_urls>"],
"resources": ["scripts/boolean-algebra/inner.js"]
}
]
}

View File

@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Answer</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.13.11/dist/katex.min.css" integrity="sha384-Um5gpz1odJg5Z4HAmzPtgZKdTBHZdw8S29IecapCSB31ligYPhHQZMIlWLYQGVoc" crossorigin="anonymous">
<link rel="stylesheet" href="style.css">
<script src="../../lib/katex.min.js" defer></script>
<script src="index.js" defer></script>
<link rel="icon"
type="image/png"
href="../../icon.png">
</head>
<body>
<div class="container"></div>
<div class="row justify-content-center my-4 mx-4">
<div class="col" id="katex"></div>
<textarea class="col" id="latex" cols="80" rows="20"></textarea>
</div>
<div class="d-flex justify-content-center my-4">
<button class="btn btn-primary text-center" id="copy">COPY</button>
</div>
</body>
</html>

View File

@ -0,0 +1,18 @@
document.getElementById("copy").onclick = () => {
document.getElementById("latex").select();
document.execCommand('copy');
}
const insertResult = (result) => {
katex.render(result, document.getElementById('katex'), {
throwOnError: false,
displayMode: true
});
document.getElementById('latex').value = result;
}
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
insertResult(message.content);
});

View File

@ -0,0 +1,7 @@
body {
background-color: #fbffd9;
}
textarea {
resize: none;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 728 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,74 @@
const valid_urls = ["https://boolean-algebra.com/"]
const bool_field = document.getElementById("bool-alg-input");
const bool_alg_btn = document.getElementById("bool-alg-btn");
const bool_alg_ab = document.getElementById('boolalg1');
const bool_alg_pl = document.getElementById('boolalg2');
const bool_alg_s = document.getElementById('boolalg3');
bool_alg_btn.addEventListener('click', () => {
chrome.runtime.sendMessage(
{
type: 'bool_alg',
content: {
expression: bool_field.value,
outputType: bool_alg_ab.checked ? 'algebra':
bool_alg_pl.checked ? 'logic' :
bool_alg_s.checked ? 'set' :
''
}
});
});
const ind_btn = document.getElementById("ind-btn");
const ind_expr1 = document.getElementById("ind-expr1");
const ind_expr2 = document.getElementById("ind-expr2");
const ind_sign = document.getElementById("ind-sign");
const ind_s = document.getElementById("ind-s");
const ind_n = document.getElementById("ind-n");
const ind_nsign = document.getElementById("ind-nsign");
const produce_induction_string = () =>
`prove by induction sum of ${ind_expr1.value} from ${ind_s.value} to n`
+ ` ${ind_sign.options[ind_sign.selectedIndex].text} ${ind_expr2.value} for n`
+ ` ${ind_nsign.options[ind_nsign.selectedIndex].text} ${ind_n.value}`;
ind_btn.addEventListener('click', () =>
chrome.runtime.sendMessage(
{
type: 'induction',
content: {expression: produce_induction_string()}
}
)
);
const perm_btn = document.getElementById('perm-btn');
const perm_n = document.getElementById('pn');
const perm_r = document.getElementById('pr');
const comb_btn = document.getElementById('comb-btn');
const comb_n = document.getElementById('cn');
const comb_r = document.getElementById('cr');
perm_btn.addEventListener('click', () =>
chrome.runtime.sendMessage(
{
type: 'perm',
content: {n: perm_n.value, r: perm_r.value}
}
)
);
comb_btn.addEventListener('click', () =>
chrome.runtime.sendMessage(
{
type: 'comb',
content: {n: comb_n.value, r: comb_r.value}
}
)
);

View File

@ -0,0 +1,165 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
<link rel="stylesheet" href="style.css"/>
<script src="lib/bootstrap.bundle.js" defer></script>
<script src="scripts/boolean-algebra.js" defer></script>
<script src="index.js" defer></script>
</head>
<body class="py-3, px-2">
<div class="container mt-3">
<h3>Math stuffs</h3>
</div>
<hr>
<div class="container">
<h4>Boolean Algebra Calc</h4>
<div class="my-2">
<input type="text" id="bool-alg-input" placeholder="A!B + !(AB)">
</div>
<div class="btn-group my-2" role="group">
<input type="radio" class="btn-check" name="boolalg" id="boolalg1" autocomplete="off" checked>
<label class="btn btn-outline-primary" for="boolalg1">Algebra</label>
<input type="radio" class="btn-check" name="boolalg" id="boolalg2" autocomplete="off">
<label class="btn btn-outline-primary" for="boolalg2">Logic</label>
<input type="radio" class="btn-check" name="boolalg" id="boolalg3" autocomplete="off">
<label class="btn btn-outline-primary" for="boolalg3">Sets</label>
</div>
<!-- <div class="btn-group" role="group" aria-label="Basic radio toggle button group">
<input type="radio" class="btn-check" name="btnradio" id="btnradio1" autocomplete="off" checked>
<label class="btn btn-outline-primary" for="btnradio1">Radio 1</label>
<input type="radio" class="btn-check" name="btnradio" id="btnradio2" autocomplete="off">
<label class="btn btn-outline-primary" for="btnradio2">Radio 2</label>
<input type="radio" class="btn-check" name="btnradio" id="btnradio3" autocomplete="off">
<label class="btn btn-outline-primary" for="btnradio3">Radio 3</label>
</div> -->
<button class="btn btn-primary" id="bool-alg-btn">Go!</button>
</div>
<hr>
<div class="container">
<h4>Proof by induction</h4>
<div class="alert alert-danger">
Fibonacci and Lucas etc. is not supported!
</div>
<div class="row">
<div class="col-3">
<img src="img/sum.png" alt="Sum from i=? to n+1" width="100%"/>
</div>
<div class="col align-self-center">
<input type="text" id="ind-expr1" class="form-control" placeholder="i^2" min="0">
</div>
</div>
<div class="row my-3">
<div class="col-1 d-flex mx-2">
<select name="exprsign" id="ind-sign" class="form-select">
<option value="gt">&gt;</option>
<option value="geq">&geq;</option>
<option value="eq" selected>=</option>
<option value="leq">&leq;</option>
<option value="lt">&lt;</option>
</select>
</div>
<div class="col">
<input type="text" id="ind-expr2" class="form-control" placeholder="n(n+1)(2n+1)/2" min="0">
</div>
</div>
<div class="row my-3">
<div class="col-5 align-self-center">
<img src="img/i.png" alt="i = " width="100%"/>
</div>
<div class="col-3 align-self-center px-0">
<input type="number" id="ind-s" class="form-control" value="0" min="0">
</div>
</div>
<div class="row">
<div class="col-3 align-self-center">
<img src="img/n.png" alt="n" width="100%"/>
</div>
<div class="col-2 d-flex">
<select name="nsign" id="ind-nsign" class="form-select">
<option value="gt">&gt;</option>
<option value="geq">&geq;</option>
</select>
</div>
<div class="col">
<input type="number" id="ind-n" class="form-control" value="0" min="0">
</div>
</div>
<!-- <div class="input-group my-2">
<input type="text" id="sy" class="form-control" placeholder="y" min="0">
</div>
<div class="input-group">
<input type="number" id="sx" class="form-control" placeholder="x" min="0">
<input type="number" id="sz" class="form-control" placeholder="z" min="0">
</div> -->
<button class="btn btn-primary" id="ind-btn">Go!</button>
</div>
<hr>
<div class="container">
<h4>Permutations, Combinations</h4>
<div class="input-group my-2">
<input type="number" id="pn" class="form-control" placeholder="n" min="0">
<span class="input-group-text">P</span>
<input type="number" id="pr" class="form-control" placeholder="r" min="0">
<button class="btn btn-primary" id="perm-btn">Go!</button>
</div>
<div class="input-group my-2">
<input type="number" id="cn" class="form-control" placeholder="n" min="0">
<span class="input-group-text">C</span>
<input type="number" id="cr" class="form-control" placeholder="r" min="0">
<button class="btn btn-primary" id="comb-btn">Go!</button>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,3 @@
body {
background-color: #fbffd9;
}

View File

@ -0,0 +1,18 @@
console.log("boolean-algebra/inner.js injected successfully!");
const redefineConsoleLog = () => {
const oldLog = console.log;
console.log = (...message) => {
if (typeof message === 'object' && Array.isArray(message) && Array.isArray(message[0])) {
window.localStorage.setItem('boolean-result', JSON.stringify(message[0][0]));
}
oldLog.apply(console, message);
};
}
redefineConsoleLog();
answerMathField.latex(window.localStorage.getItem('boolean-expression'));
document.getElementById('submit-btn').click();

View File

@ -0,0 +1,141 @@
console.log("boolean-algebra/outer.js injected successfully!");
const injectInnerScript = () => {
const s = document.createElement('script');
s.src = chrome.runtime.getURL('scripts/boolean-algebra/inner.js');
(document.head || document.documentElement).appendChild(s);
}
const replaceParens = (parens, counterParens, replacements, text) => {
parPattern = RegExp(`${parens[0]}.*${parens[1]}`);
while (parPattern.test(text)) {
const match = RegExp(parens[0], 'g').exec(text);
let i = match.index + match[0].length;
let parCount = 1;
while (parCount != 0) {
if (text[i] == counterParens[0]) parCount++;
if (text[i] == counterParens[1]) parCount--;
i++;
}
const secondPar = parens[1].replace(/\\(?!\\)/g, '').replace(/\\\\/,'\\');
text = text.substring(0, match.index)
+ replacements[0] + text.substring(match.index + match[0].length, i - secondPar.length)
+ replacements[1] + text.substring(i);
}
return text;
}
const parseExpression = (expression) => {
expression = replaceParens(["!\\(", "\\)"], ["(", ")"], ["\\overline{", "}"], expression);
expression = expression.replace(/!([A-Za-z01])/g, '\\overline{$1}');
return expression;
}
const insertExpression = (expression) => {
localStorage.setItem('boolean-expression', parseExpression(expression));
injectInnerScript();
}
const parseLatex = resultArray => {
const lines = [];
lines.push('\\begin{array}{ccl}');
for ([latex, comment] of resultArray) {
let l = latex;
l = replaceParens(['\\\\class{[-\\w]+}{', '}'], ['{', '}'], ['',''], l);
const lawTable = [
["Distributive", "Distributive law"],
["Demorgan", "Demorgan theorem"],
["Involution", "Involution law"],
["Distribution", "Distributive law"],
["Identity", "Identity law"],
["Complement", "Complement law"],
["Associative", "Associative law"],
["Idempotent", "Associative law"],
["Absorption", "Absorption law"],
];
let c = '&\\qquad&';
for (law of lawTable) {
if (comment.includes(law[0]))
c = ` &\\qquad& \\text{${law[1]}}`;
}
lines.push(`${l}${c} \\\\`);
}
lines.push('\\end{array}');
return lines.join('\n');
}
const whileFindReplace = (pattern, replacement, text) => {
while (pattern.test(text))
text = text.replace(pattern, replacement);
return text;
}
const convertToPropositionalLogic = latex => {
// replace neg
latex = replaceParens(['\\\\overline{', '}'], ['{', '}'], ['\\neg ', ''], latex);
// replace and
latex = whileFindReplace(/\b(?!\\cup|\\cap|\\text|\\quad)([A-Z0-9]|\\overline{.+})([A-Z0-9]|\\overline{.+?})(?=[\s\+])/, '($1 \\wedge $2)', latex);
// // replace or
latex = latex.replace(/\+/g, ' \\vee ');
return latex;
}
const convertToSetTheory = latex => {
// replace and
latex = whileFindReplace(/\b(?!\\cup|\\cap|\\text|\\quad)([A-Z0-9]|\\overline{.+})([A-Z0-9]|\\overline{.+?})(?=[\s\+])/, '($1 \\cap $2)', latex);
// // replace or
latex = latex.replace(/\+/g, ' \\cup ');
return latex;
}
const getLatex = () => {
return parseLatex(JSON.parse(localStorage.getItem('boolean-result')));
}
const timeout = (ms) => new Promise(resolve => setTimeout(resolve, ms));
const calculateExpression = async (expression) => {
console.log("Inserting expression");
insertExpression(expression);
await timeout(2);
return getLatex();
}
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
console.log("Checking Message Type");
if (message.type !== "bool_alg") return;
calculateExpression(message.content.expression)
.then(latex => sendResponse({
content: message.content.outputType === 'logic' ? convertToPropositionalLogic(latex) :
message.content.outputType === 'set' ? convertToSetTheory(latex) :
latex
}));
return true;
});

View File

@ -0,0 +1,29 @@
console.log("induction/outer.js injected successfully!");
const getButtonContainingText = (text) =>
[...document.getElementsByTagName('button')].filter(b => b.innerText === text)[0];
const latexifyPage = () => {
return "";
}
const getContent = async () => {
getButtonContainingText('Step-by-step solution').click();
getButtonContainingText('Show all steps').click();
return latexifyPage();
}
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
console.log("Checking Message Type");
if (message.type !== "induction") return;
getContent()
.then(latex => {
sendResponse({ content: latex });
});
return true;
});