Upload files to 'maydo/keyzen'

This commit is contained in:
zensprojects 2023-02-21 19:14:53 +00:00
parent ae3af9b79c
commit 948134c52b
5 changed files with 451 additions and 0 deletions

3
maydo/keyzen/README Normal file
View File

@ -0,0 +1,3 @@
app_icon aquired from
http://commons.wikimedia.org/wiki/File:Crystal_Clear_app_keyboard.png

355
maydo/keyzen/keyzen.js Normal file
View File

@ -0,0 +1,355 @@
var data = {};
var audio = {};
var hits_correct = 0;
var hits_wrong = 0;
var start_time = 0;
var hpm = 0;
var ratio = 0;
data.chars = " jfkdlsahgyturieowpqbnvmcxz6758493021`-=[]\\;',./ABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()_+{}|:\"<>?";
data.consecutive = 5;
data.word_length = 7;
data.current_layout = "qwerty";
layouts={};
layouts["qwerty"] = " jfkdlsahgyturieowpqbnvmcxz6758493021`-=[]\\;',./ABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()_+{}|:\"<>?";
layouts["azerty"] = " jfkdlsmqhgyturieozpabnvcxw6758493021`-=[]\\;',./ABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()_+{}|:\"<>?";
layouts["colemak"] = " ntesiroahdjglpufywqbkvmcxz1234567890'\",.!?:;/@$%&#*()_ABCDEFGHIJKLMNOPQRSTUVWXYZ~+-={}|^<>`[]\\";
layouts["bépo"] = " tesirunamc,èvodpléjbk'.qxghyfàzw6758493021`-=[]\\;/ABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()_+{}|:\"<>?";
layouts["norman"] = " ntieosaygjkufrdlw;qbpvmcxz1234567890'\",.!?:;/@$%&#*()_ABCDEFGHIJKLMNOPQRSTUVWXYZ~+-={}|^<>`[]\\";
layouts["code-es6"] = " {}',;():.>=</_-|`!?#[]\\+\"@$%&*~^";
$(document).ready(function() {
load_audio();
if (localStorage.data != undefined) {
load();
render();
}
else {
set_level(1);
}
$(document).keypress(keyHandler);
});
function start_stats() {
start_time = start_time || Math.floor(new Date().getTime() / 1000);
}
function update_stats() {
if (start_time) {
var current_time = (Math.floor(new Date().getTime() / 1000));
ratio = Math.floor(
hits_correct / (hits_correct + hits_wrong) * 100
);
hpm = Math.floor(
(hits_correct + hits_wrong) / (current_time - start_time) * 60
);
if (!isFinite(hpm)) { hpm = 0; }
}
}
function set_level(l) {
data.in_a_row = {};
for(var i = 0; i < data.chars.length; i++) {
data.in_a_row[data.chars[i]] = data.consecutive;
}
data.in_a_row[data.chars[l]] = 0;
data.level = l;
data.word_index = 0;
data.word_errors = {};
data.word = generate_word();
data.keys_hit = "";
save();
render();
}
function set_layout(l) {
data.current_layout = l
data.chars = layouts[l]
data.in_a_row = {};
for(var i = 0; i < data.chars.length; i++) {
data.in_a_row[data.chars[i]] = data.consecutive;
}
data.word_index = 0;
data.word_errors = {};
data.word = generate_word();
data.keys_hit = "";
save();
render();
}
function keyHandler(e) {
start_stats();
var key = String.fromCharCode(e.which);
if (data.chars.indexOf(key) > -1){
e.preventDefault();
}
else {
return;
}
data.keys_hit += key;
if(key == data.word[data.word_index]) {
hits_correct += 1;
data.in_a_row[key] += 1;
play_audio_sample("correct");
}
else {
hits_wrong += 1;
data.in_a_row[data.word[data.word_index]] = 0;
data.in_a_row[key] = 0;
play_audio_sample("mistake");
data.word_errors[data.word_index] = true;
}
data.word_index += 1;
if (data.word_index >= data.word.length) {
setTimeout(next_word, 400);
}
update_stats();
render();
save();
}
function next_word(){
if(get_training_chars().length == 0) {
level_up();
}
data.word = generate_word();
data.word_index = 0;
data.keys_hit = "";
data.word_errors = {};
update_stats();
render();
save();
}
function level_up() {
if (data.level + 1 <= data.chars.length - 1) {
play_audio_sample("level_up");
}
l = Math.min(data.level + 1, data.chars.length);
set_level(l);
}
function save() {
localStorage.data = JSON.stringify(data);
}
function load() {
data = JSON.parse(localStorage.data);
}
function load_audio() {
audio.samples = {};
audio.context = new (window.AudioContext || window.webkitAudioContext)();
load_audio_sample("correct", "click.wav");
load_audio_sample("mistake", "clack.wav");
load_audio_sample("level_up", "ding.wav");
}
function load_audio_sample(name, url) {
if (!audio.samples[name]) {
// fetch the .wav file via XMLHttpRequest as jQuery doesn't support 'arraybuffer' dataType
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.responseType = "arraybuffer";
request.onload = function () {
audio.context.decodeAudioData(request.response).then(function (buffer) {
audio.samples[name] = buffer;
});
};
request.send();
}
}
function play_audio_sample(name) {
if (audio.samples[name]) {
var source = audio.context.createBufferSource();
source.buffer = audio.samples[name];
source.onended
source.connect(audio.context.destination);
source.start();
}
}
function render() {
render_layout();
render_level();
render_word();
render_level_bar();
render_rigor();
render_stats();
}
function render_layout() {
var layouts_html = "<span id='layout'>";
for(var layout in layouts){
if(data.current_layout == layout){
layouts_html += "<span style='color: #F00' onclick='set_layout(\"" + layout + "\");'> "
} else {
layouts_html += "<span style='color: #AAA' onclick='set_layout(\"" + layout + "\");'> "
}
layouts_html += layout + "</span>";
}
layouts_html += "</span>";
$("#layout").html('Choose layout : ' + layouts_html);
}
function render_level() {
var chars = "<span id='level-chars-wrap'>";
var level_chars = get_level_chars();
var training_chars = get_training_chars();
for (var c in data.chars) {
if(training_chars.indexOf(data.chars[c]) != -1) {
chars += "<span style='color: #F00' onclick='set_level(" + c + ");'>"
}
else if (level_chars.indexOf(data.chars[c]) != -1) {
chars += "<span style='color: #000' onclick='set_level(" + c + ");'>"
}
else {
chars += "<span style='color: #AAA' onclick='set_level(" + c + ");'>"
}
if (data.chars[c] == ' ') {
chars += "&#9141;";
}
else {
chars += data.chars[c];
}
chars += "</span>";
}
chars += "</span>";
$("#level-chars").html('click to set level: ' + chars);
}
function render_rigor() {
chars = "<span id='rigor-number' onclick='inc_rigor();'>";
chars += '' + data.consecutive;
chars += '<span>';
$('#rigor').html('click to set required repititions: ' + chars);
}
function render_stats() {
$("#stats").text([
"hits per minute: ", hpm, " ",
"correctness: ", ratio, "%"
].join(""));
}
function inc_rigor() {
data.consecutive += 1;
if (data.consecutive > 9) {
data.consecutive = 2;
}
render_rigor();
}
function render_level_bar() {
training_chars = get_training_chars();
if(training_chars.length == 0) {
m = data.consecutive;
}
else {
m = 1e100;
for(c in training_chars) {
m = Math.min(data.in_a_row[training_chars[c]], m);
}
}
m = Math.floor($('#level-chars-wrap').innerWidth() * Math.min(1.0, m / data.consecutive));
$('#next-level').css({'width': '' + m + 'px'});
}
function render_word() {
var word = "";
for (var i = 0; i < data.word.length; i++) {
sclass = "normalChar";
if (i > data.word_index) {
sclass = "normalChar";
}
else if (i == data.word_index) {
sclass = "currentChar";
}
else if(data.word_errors[i]) {
sclass = "errorChar";
}
else {
sclass = "goodChar";
}
word += "<span class='" + sclass + "'>";
if(data.word[i] == " ") {
word += "&#9141;"
}
else if(data.word[i] == "&") {
word += "&amp;"
}
else {
word += data.word[i];
}
word += "</span>";
}
var keys_hit = "<span class='keys-hit'>";
for(var d in data.keys_hit) {
if (data.keys_hit[d] == ' ') {
keys_hit += "&#9141;";
}
else if (data.keys_hit[d] == '&') {
keys_hit += "&amp;";
}
else {
keys_hit += data.keys_hit[d];
}
}
for(var i = data.word_index; i < data.word_length; i++) {
keys_hit += "&nbsp;";
}
keys_hit += "</span>";
$("#word").html(word + "<br>" + keys_hit);
}
function generate_word() {
word = '';
for(var i = 0; i < data.word_length; i++) {
c = choose(get_training_chars());
if(c != undefined && c != word[word.length-1]) {
word += c;
}
else {
word += choose(get_level_chars());
}
}
return word;
}
function get_level_chars() {
return data.chars.slice(0, data.level + 1).split('');
}
function get_training_chars() {
var training_chars = [];
var level_chars = get_level_chars();
for(var x in level_chars) {
if (data.in_a_row[level_chars[x]] < data.consecutive) {
training_chars.push(level_chars[x]);
}
}
return training_chars;
}
function choose(a) {
return a[Math.floor(Math.random() * a.length)];
}

78
maydo/keyzen/logo.svg Normal file
View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="172.1498"
height="172.1498"
id="svg2"
version="1.1"
inkscape:version="0.48.1 r9760"
sodipodi:docname="logo.svg"
inkscape:export-filename="/home/rye/Dropbox/projects/keyzen/favicon.ico.png"
inkscape:export-xdpi="8.3599997"
inkscape:export-ydpi="8.3599997">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="90.162846"
inkscape:cy="104.10844"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="917"
inkscape:window-height="610"
inkscape:window-x="359"
inkscape:window-y="103"
inkscape:window-maximized="0" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-248.03307,-459.94833)">
<text
xml:space="preserve"
style="font-size:49.96237564px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ff6600;fill-opacity:1;stroke:none;font-family:Sans"
x="240.77084"
y="663.97345"
id="text3755"
sodipodi:linespacing="125%"
transform="scale(1.0633781,0.94039928)"
inkscape:export-xdpi="8.3599997"
inkscape:export-ydpi="8.3599997"><tspan
sodipodi:role="line"
id="tspan3757"
x="240.77084"
y="663.97345"
style="font-size:239.81939697px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu Bold">Z</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,15 @@
{
// Required
"name": "KeyZen",
"version": "1.0",
"description": "A touch typing app for Chrome, src is @ https://github.com/wwwtyro/keyzen",
"icons": {
"128": "app_icon.png"
},
"app": {
"launch": {
"local_path": "index.html"
}
}
}

Binary file not shown.