我正在用Anki帮助我的5年级儿子学习数学。我的儿子已经到了需要重新审视如何解决特定问题而不是简单地记住事实的地步。
例如,假设您正在尝试学习如何将分数相乘... .45 X .61 =?
我需要一种将随机数学问题放入Anki卡中的方法。这意味着该卡将有一天显示 .45 X .61 =? 下次显示该卡时,可能会出现问题。 .34 X .12 =?
在浏览互联网后,我能够找到一篇文章来说明如何执行此操作...
https://yingtongli.me/blog/2015/03/15/random-question-generator-on-anki-using.html
我不是JavaScript开发人员,但是在敲打键盘一周后,我才能够使用此技术。
让我解释一下您如何执行此操作,然后再解释问题出在哪里。
安装Anki的2.0版本。
打开Anki并创建一个新的牌组。
向卡组添加新卡。
出现添加卡对话框。最顶部是两个长按钮...“类型”和“甲板”。单击左侧的“类型”按钮。
出现“选择注释类型”对话框。
单击对话框底部的“管理”按钮。
选择基本注释类型,然后单击左侧的“添加”按钮。
第一个选项应为“添加基本”。单击对话框底部的“确定”按钮。
命名新的笔记类型。“脚本笔记类型”,然后单击“确定”
逃脱。
现在选择新的注释类型(“脚本注释类型”),然后单击“选择”。
现在,我们要添加一个附加字段。默认情况下,此注释类型具有名为“ Front”和“ Back”的字段。我们要添加第三个名为“脚本”的字段。
在左上角附近有一个标记为“字段”的按钮。点击这个按钮。
出现另一个对话框。左侧是“添加”按钮。点击它。
在出现的对话框中输入脚本,然后单击“确定”按钮。
现在通过单击右侧按钮附近的关闭按钮来关闭当前对话框。
现在就设置我们的卡。当前屏幕左上方附近有两个按钮。右边的按钮标记为“卡”。单击此按钮。
这是我们设置卡模板的地方。 JavaScript代码的一部分进入了Front Template。当前此处应包含以下文本...
{{Front}}
删除所有内容并粘贴以下代码。
<script>
function persist(cb) {
window.setTimeout(function() {
// Determine whether to use Anki's Bridge object (Desktop) or sessionStorage (AnkiDroid) to store data across sides.
var dummy = {};
var mode = "dummy";
if (typeof(py) !== "undefined") {
mode = "py";
py.data = py.data || {};
} else if (typeof(sessionStorage) !== "undefined") {
mode = "sessionStorage";
}
var dataObj = {
setItem: function(key, val) {
if (mode === "dummy") {
dummy[key] = val;
} else if (mode === "py") {
py.data[key] = val;
} else if (mode === "sessionStorage") {
sessionStorage.setItem(key, val);
}
},
getItem: function(key, def) {
var val = undefined;
if (mode === "dummy") {
val = dummy[key];
} else if (mode === "py") {
val = py.data[key];
} else if (mode === "sessionStorage") {
val = sessionStorage.getItem(key);
}
if (val == null) {
return def;
} else {
return val;
}
},
tryItem: function(key, val) {
var currVal = dataObj.getItem(key, undefined);
if (currVal == null) {
dataObj.setItem(key, val);
return val;
} else {
return currVal;
}
},
clear: function() {
if (mode === "dummy") {
dummy = {};
} else if (mode === "py") {
window.py.data = {};
} else if (mode === "sessionStorage") {
sessionStorage.clear();
}
}
};
if (!document.getElementById("back")) {
dataObj.clear();
}
cb(dataObj);
}, 0); //Execute after Anki has loaded its Bridge object.
}
</script>
<script>
var code = (function () {/* {{Script}} */}).toString();
code = code.replace(/^[^\/]+\/\*!?/, "").replace(/\*\/[^\/]+$/, ""); //Strip beginning/ending comments.
code = code.replace(/<div>/g, "\n").replace(/<\/div>/g, "\n").replace(/<br \/>/g, "\n"); //Strip HTML.
code = code.replace(/ /g, " ").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&"); //Replace special symbols.
eval(code);
</script>
<div id="front">{{Front}}</div>
此JavaScript接收我们将放置在“脚本”字段中的JavaScrippt代码,并使用eval语句执行该代码。
在此代码中请注意persist函数,该函数可使Anki卡的正面和背面的值保持一致。我的问题与此持久功能有关。
在屏幕的底部三分之一是“返回模板”。删除所有内容并粘贴以下代码...
{{FrontSide}}
<hr id=answer>
<div id="back">{{Back}}</div>
在右下角单击“关闭”按钮。
现在我们需要填写字段。前面和后面的值无关紧要。我将“ Front”放在前面,将“ Back”放在后面。
对于“脚本”字段,我们要添加一些代码。粘贴代码之前,我们需要打开HTML视图。确保光标位于“脚本”字段中。
在Anki 2.0版中,屏幕右上方有一个带有向下箭头图片的按钮。 2.1版本带有“ ...”而不是向下箭头按钮。
单击此箭头,将显示一个菜单。选择“编辑HTML”菜单选项。
粘贴以下代码...
window.setTimeout(function(){
persist(function(data) {
var num1 = data.tryItem("num1",Math.random());
document.getElementById("front").innerHTML = num1;
document.getElementById("back").innerHTML = num1;
});
},0);
这在Anki的2.0版本中有效。
这是问题
这是答案...
我们在JavaScript中生成了一个随机数,该值一直保留在Anki卡的正面和背面之间。这为使用随机数的Math和Science Anki卡开辟了可能性世界。
但是,在Whoville中一切都不好。
在Anki的2.1版本上运行此代码时,它将不起作用。
绕过脚本,并显示“前”和“后”字段的静态值。
JavaScript仍在执行。我可以在Script字段中添加警报语句,它可以工作。
问题在于持久功能。较新版本的Anki不喜欢Persist功能。
谁能指出我正确的方向。
答案 0 :(得分:2)
我知道了...
问题是Anki 2.1取消了在window.py对象中存储持久数据的功能。
现在您可能正在问(就像我一样)window.py对象是什么?我不确定100%,但是我相信它是一个内部Python对象,该对象允许JavaScript和Python之间进行某些交互。 Anki是用Python编写的。
在任何情况下,anki 2.1都无法访问window.py,这意味着我在问题中描述的技术(见上文)在Anki 2.1中不再起作用。
幸运的是,作者(该问题在上文中提到)的文章提到,在Anki卡问题和答案的调用之间共享窗口对象。
我开始使用Javascript来处理窗口对象,并且能够在Anki 2.1中获得数据持久性(在Anki 2.0中也是如此)
在上面的问题中,我深入研究了此技术,以在您的Anki卡中生成持久的随机值。这意味着您在问题中生成一个随机数,并且答案中可以使用相同的值。在这里,我将不做详细介绍,但请参考上面的问题以获取更多详细信息。
代码在“前模板”中。
<script>
var code = (function () {/* {{Script}} */}).toString();
code = code.replace(/^[^\/]+\/\*!?/, "").replace(/\*\/[^\/]+$/, ""); //Strip beginning/ending comments.
code = code.replace(/<div>/g, "\n").replace(/<\/div>/g, "\n").replace(/<br \/>/g, "\n"); //Strip HTML.
code = code.replace(/ /g, " ").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&"); //Replace special symbols.
eval(code);
</script>
<div id="front">{{Front}}</div>
这与文章中的代码相同。我只是删除了一些不再起作用的代码。
这是卡片脚本代码...
window.setTimeout(function(){
var windowsref = window; //Set a reference to the window object
if ((("num1" in windowsref) == false) || windowsref.cnt != 1) {
windowsref.num1 = Math.random();
windowsref.cnt = 0;
}
windowsref.cnt++;
document.getElementById("front").innerHTML = windowsref.num1;
document.getElementById("back").innerHTML = windowsref.num1;
},0);
此代码仅在Anki 2.1桌面上有效。我还测试了iOS,它也可以正常运行。
我希望这对其他人有帮助。
答案 1 :(得分:2)
退房 https://github.com/SimonLammer/anki-persistence 它使用不同的方法来实现持久性。
但是Anki环境在某种程度上是不可预测的,您需要检查代码是否已成功初始化。
答案 2 :(得分:1)
很高兴得知您找到了解决方案,编码专家。
有关更多信息,我想添加 我在2014年左右涉足相同的想法。 我可以在笔记模板中使用JavaScript和Cookies来使其工作。
为此,我不得不使用一个插件(以Qt Web视图的猴子补丁创建)来修改Anki,该插件以Anki 2.0 plugin JS Booster的身份共享。 改用Anki 2.1后,另一位开发人员在Anki 2.1 plugin Cookie Monster处发布了相同的解决方案。