Алгоритм для запоминания иностранных слов

    На данный момент создано множество приложений для запоминания слов. Из тех что мне запомнились могу выделить такие Android приложения как Lingualeo, Английские слова, СловоУч.

    Главным недостатком этих приложений для меня был платный аккаунт для добавления своей базы слов. Поэтому встал вопрос о написании своего приложения для запоминания слов. Главной идеей было подключения внешнего API словаря и переводчика для переводов слов на родной язык. В качестве такого API было выбрано Yandex API (API Переводчика и API Словаря).

    Первым делом необходимо было получить ключи разработчика. Для переводчика и для словаря.

    В качестве языка и платформы разработки был выбран JavaScript и библиотека JQuery.

    Для получения перевода слова на нужный язык я использовал следующий код:

                var oneWord = function() {
                    $.post("https://dictionary.yandex.net/api/v1/dicservice.json/lookup",
                        {
                            key: apiKey, 
                            lang: lang, 
                            text: words[index].text
                        }, function(data) 
                        {
                            words[index].tr = "";
                            words[index].ts = "";
                            for (var j = 0; j < data.def.length; j++) {
                                var def = data.def[j];
                                for (var k = 0; k < def.tr.length; k++) {
                                    var tr = def.tr[k];
                                    words[index].tr += tr.text + "; ";
                                }					
                                if (def.ts)
                                    words[index].ts = def.ts;
                            }
                            if (words[index].tr == "") {
                                translateWords();
                                tsWords();
                                return;
                            } else {
                                var str = words[index].tr;
                                words[index].tr = str.substring(0, str.length - 2);
                            }
                            complete();
                        }, 
                    "json");
                };
                var tsWords = function() {
                    var text = words[index].text;
                    var tsText = "";
                    var tsWords = text.match(/\S+/gi);
                    var tsIndex = 0;
                    var tsPost = function() {
                        $.post("https://dictionary.yandex.net/api/v1/dicservice.json/lookup",
                            {
                                key: apiKey, 
                                lang: lang, 
                                text: tsWords[tsIndex]
                            }, function(data) 
                            {
                                var ts = "";
                                for (var j = 0; j < data.def.length; j++) {
                                        var def = data.def[j];
                                        if (def.ts)
                                                ts = def.ts;
                                }
                                tsText += ts + " ";
                                if ((tsIndex < (tsWords.length - 1)) && (tsIndex < 5)) {
                                    tsIndex++;
                                    tsPost();
                                } else {
                                    words[index].ts = tsText.trim();
                                    complete(false, true);
                                }
                            },
                        "json");
                    };
                    tsPost();
                };
                var translateWords = function() {
                    $.post("https://translate.yandex.net/api/v1.5/tr.json/translate",
                        {
                            key: apiKeyTranslate, 
                            lang: slang, 
                            text: words[index].text
                        }, function(data) 
                        {
                            words[index].tr = "";
                            for (var j = 0; j < data.text.length; j++) {
                                var text = data.text[j];
                                words[index].tr += text + "; ";
                            }
                            var str = words[index].tr;
                            words[index].tr = str.substring(0, str.length - 2);
                            complete(true, false);
                        },
                    "json");
                };
                var qu = function() {
                    if (!words[index].tr) {
                        oneWord();
                    } else {
                        complete();
                    } 
                };
                qu();
    

    Тут функция oneWord переводит одно слово, tsWords находит транскрипции первых пяти слов в выражении (если дано не слово, а предложение), translateWords переводит предложение.

    Результирующая функция complete вызывается для заполнения формы слова с транскрипцией и переводом:

            var complete = function(tr, ts) {
                if (ts == undefined) ts = true;
                if (tr == undefined) tr = true;
                var word = words[index];
                if (tr) $("#text").html(word.text);
                if (ts) $("#ts").html("[" + word.ts + "]");
                $("#tr").hide();
                $("#attempt").hide();
                $("#show").show();
                $("#tr").html(word.tr);
                $("#tts").show();
            };
    

    В массиве слов words index отражает текущее слова для запоминания. Следующее слово выбирается по следующему алгоритму:

            var words = [],
                patternCount = 5,
                indexMemory = {},
                indexMemoryCount = 0,
                patternIndex = [],
                lastIndex = -1,
                lastIndexs = [],
                lastIndexsCount =  2,
                wasAttempt = false,
                wasMemory = false,
                deep = 0,
                deepMax = 100; 
    
            var index = nextIndex();
    
            var nextIndex = function() {
                deep++;
                if (lastIndexsCount - words.length >= 0) {
                    lastIndexsCount = 0;
                } 
                if ((patternIndex.length < patternCount) && (indexMemoryCount < words.length)) {
                    if (deep > deepMax) {
                        
                        var index = maxAttemptsIndex(true);
                        return index;
                    }
                    var index = Math.floor(Math.random() * words.length);
                    if (indexMemory[index]) {
                        return nextIndex();
                    }
                    indexMemory[index] = "do";
                    indexMemoryCount++;
                    patternIndex.push(index);
                    lastIndex = index;
                    pushIndex(lastIndex);
                    return index;
                } else {
                    var index = Math.floor(Math.random() * (patternIndex.length + 1));
                    if (index == patternIndex.length || (patternIndex.length == 0)) {
                        wasMemory = true;
                        var ind = maxAttemptsIndex();
                        if (inArray(lastIndexs, ind)) 
                        {
                            if (deep > deepMax) {
                                ind = Math.floor(Math.random() * words.length);
                                lastIndex = ind;
                                pushIndex(lastIndex);
                                return ind;
                            }
                            return nextIndex();
                        }
                        lastIndex = ind;
                        pushIndex(lastIndex);
                        return ind;
                    }
                    if (inArray(lastIndexs, patternIndex[index])) return nextIndex();
                    lastIndex = patternIndex[index];
                    pushIndex(lastIndex);
                    return patternIndex[index];
                }
            };
    
            var maxAttemptsIndex = function(notAttempts) {
                var arr = sortMemoryIndexes(indexMemory);
                var index = getRandomFishIndex(arr, notAttempts);
                return index;
            };
    
           var pushIndex = function(index) {
                if (lastIndexsCount == 0) return;
                if (lastIndexs.length < lastIndexsCount) {
                    lastIndexs.push(index);
                } else {
                    lastIndexs[0] = lastIndexs[1];
                    lastIndexs[1] = index;
                }
            };
    
            var inArray = function(arr, elem) {
                for (var i = 0; i < arr.length; i++) {
                    if (arr[i] == elem) 
                        return true;
                }
                return false;
            };
    
            function getRandomFishIndex(arr, notAttempts) {
                var fishForLevel = arr;
                var fishTotalWeight = 0, fishCumWeight = 0, i;
                // sum up the weights
                for (i = 0; i < fishForLevel.length; i++) {
                    fishTotalWeight += fishForLevel[i].attempts;
                }
                if (notAttempts) {
                    fishTotalWeight = 0;
                }
                var random = Math.floor(Math.random() * fishTotalWeight);
                // now find which bucket out random value is in
                if (fishTotalWeight == 0) return fishForLevel[Math.floor(Math.random() * fishForLevel.length)].index;
                for (i = 0; i < fishForLevel.length; i++) {
                    fishCumWeight += fishForLevel[i].attempts;
                    if (random <= fishCumWeight) {
                        return fishForLevel[i].index;
                    }
                }
            }
    
            function sortMemoryIndexes(indexMemory) {
                var arr = [];
                for (var key in indexMemory) {
                    if (indexMemory[key] == "do") {
                        var word = jQuery.extend(true, {}, words[key]);
                        word.index = key;
                        arr.push(word);
                    }
                }
                var sAttempt = function(first, second) {
                    if (first.attempts < second.attempts)
                        return 1;
                    else if (first.attempts > second.attempts)
                        return -1;
                    else
                        return 0;
                };
                return arr.sort(sAttempt);
            }
    

    Суть в том, что требуется выбрать следующее слово из набора ранее не изученных, а также предыдущих изученных слов. При этом вероятность показа последних должна быть больше, если слово плохо запоминается.

    Именно кнопка «Неправильно» реализует перестановку вероятностей показа слов.

            $("#attempt").click(function()
            { 
                words[index].attempts++;
                wasAttempt = true;
                $("#attempt").hide();
            });
    

    Данный метод запоминания слов показался мне наиболее эффективным. В остальном программный код приложения реализует события и действия элементов интерфейса. HTML и сопутствующий JavaScript код был обернут в Cordova для платформы Android.

    Приложение «EnglishWords» позволяет учить английские слова и слова многих других языков. В программе имеется базовый набор слов для изучения. Главной особенностью программы является возможность создавать свои наборы слов для изучения. ИНФОРМАЦИЯ НА ЭКРАНЕ * Процент. Означает процент изученных слов в словаре. КАК ЭТО РАБОТАЕТ. Процесс изучения слов начинается с того, что программа набирает из выбранных словарей 5 случайных слов и начинает их показывать в случайном порядке. После того, как слова выучены из словаря извлекаются следующие 5 случайных слов. Если вы отвечаете не правильно на слово, то слово будет показываться чаще. Когда все слова выучены показываются только те слова на которые чаще всего давался не правильный ответ. СЛОВАРЬ Базовый набор слов содержит около 1000 наиболее употребляемых английских слов.

    Приложение использует yandex и google api для получения перевода, транскрипции и звукового воспроизведения. Для работы приложения необходим доступ в интернет.

    Приведу скриншоты приложения:

    Share post

    Comments 26

      0
      Приложение доступно в Play Маркете по адресу:
      https://play.google.com/store/apps/details?id=svlab.englishwords

      Также доступна web версия приложения по адресу:
      https://svlaboratory.org/application/english-words
      • UFO just landed and posted this here
          0
          2) Как быть, если хочется поучить слова, скажем, узбекского языка?

          Приложение доступно в Play Маркете по адресу:
          https://play.google.com/store/apps/details?id=com.ichi2.anki
          • UFO just landed and posted this here
              0
              Надёргать и импортировать (например, отсюда) можно везде, но у автора главный недостаток — платный акаунт. Решать его написанием приложения, при существующем anki, решение довольно спорное. Уж поверьте мне, я сам когда-то таким занимался, но исключительно из за того, что на нужной мне платформе не было anki.

            0
            1) Используйте HTTP:
            http://svlaboratory.org/application/english-words
            2) В интерфейсе приложения приведены возможные направления переводов:
            ru, en, pl, uk, de, fr, es, it, tr.
            К сожалению Yandex API не предоставляет возможность переводов для узбекского языка.
              0
              Здравствуйте, попробуйте это приложение, старался создать универсальное приложение для изучения слов любого иностарнного языка. Различного функционала и настроек очень много. Полностью бесплатное. https://play.google.com/store/apps/details?id=com.jdev.tutor
              0

              Заведите пожалуйста свою тему на 4pda.ru
              Я, как и многие, использую прошивку без play market.
              И почините сертификат на svlaboratory.org, а то страшно заходить.
              Спасибо.

            +2

            Хорошо, но изучили ли вы опыт предшественников? Конкретнее — посмотрите на anki, там заметно более продвинутый, чем у вас, алгоритм выбора момента показа слов.


            Из функционала, который стОит сделать — интегрироваться со словарями на смартфоне. У многих есть возможность получить history — соответственно, её добавление в список для заучивания — идеально. Читаешь себе книжку на иностранном языке, смотришь незнакомые слова в словаре (лично я использую связку AlReader + GoldenDict, длинный тап на незнакомое слово), а потом повторяешь выписанные слова.

              0
              В моем приложении присутствует сервис для мгновенного добавления слов. Скопировал слово и добавил в словари. На подобии google translater. https://play.google.com/store/apps/details?id=com.jdev.tutor
              Попробуйте, может Вам понравится.
                0

                Всё равно при чтении в словарь заглядываю, а он историю пишет. Нет смысла слово вначале смотреть в словаре, потом добавлять в прогу — лучше сделать всё в одно действие. Тем паче в словарь я заглядываю гораздо проще, чем "скопировать и добавить" — просто long tap (а могу перенастроить — и буду смотреть просто по тапу на слово).


                Хотя "скопировал и добавил", конечно, тоже полезная фича (как и обычно применяющаяся вместо неё в словарях андроидная фича "share").


                Подробнее на прогу посмотрю, да (хотя пока предпочитаю AnkiDroid).

              0
              Хм, идея хорошая, но реализация подкачала. Я уже некоторое время думаю над своим решением, и концепцию офлайна я уже придумал. Ваша же статья привела меня к несколько другой мысли. В общем, пойду работать дальше, возможно, довольно скоро, приведу свой вариант)
                +6
                Заголовок вводит в заблуждение, когда я читаю «Алгоритм для запоминания» я жду что будет что то связанное с тем как запоминать в голове, а не на компьютер.
                А главный недостаток сервисов всех что я видел, то что они скрывают статистику(скорее всего удручающую) по использованию их сервиса.
                  0
                  Система запоминания слов «по карточкам» неэффективна. Я даже статью писал на эту тему. Слова существуют вне контекста, а запоминаются лишь из-за частого мелькания на экране телефона и дальше, чем в кратковременную память, не попадают. Но я понял, что пост вовсе не об этом :)
                  • UFO just landed and posted this here
                      0
                      Именно так. С карточками можно набрать только базовый набор слов, которые постоянно встречаешь в текстах. И именно факт их использования в реальной ситуации помогает из запомнить.

                      При учебе по карточкам за собой заменил следующую тенденцию — выучиваю слово, пауза между повторениями увеличивается, и когда доходит до 3-6 месяцев, я его забываю и все начинается сначала. Также обратил внимание, что иногда встретив в тексте слово, узнаю его, но не помню значения, затем вспоминаю где встречал его в прошлый раз, и по прошлому контексту вспоминаю значение.

                      Идеальным алгоритмом было бы изучение слов по карточкам, затем чтение текстов из этих слов, затем составление текстов из них же.
                        0
                        То есть, мы приходим к дуо лингво?)

                        Пока не встречал более удобного приложения, а стремление разработчиков получить деньги тоже вполне оправдано — на разработку качественного продукта и его поддержку уходит много времени. Это, кстати, влечёт за собой тот неочевидный факт, что силами одного разработчика сложно реализовать что-то равноценное(если конечно нет какой-либо новой прорывной идеи).
                          0
                          Дуо лингво хорошо, но только для начинающих. Хотелось бы видеть там более продвинутые уровни.
                            0

                            Когда смотрел Duolingo последний раз, он обучал паре сотен слов, на практике это бесполезно, нужно пара тысяч, что бы хоть какие-то тексты понимать, кроме обучающих. Т.е. все равно нужен другой инструмент.

                            • UFO just landed and posted this here
                              0
                              Попробуйте Lingvist.
                            0

                            Слова имеет смысл учить перед чтением текста. Сначала учатся незнакомые слова из текста (в кратковременную память достаточно), потом читается текст. Словарь не нужен, запоминание в разы лучше, чем после листания словаря, процесс приятнее. Один минус — отфильтровать именно незнакомые слова, программ не видел, делал скрипт на коленке.

                              0

                              Есть чувство, что карточки наиболее полезны, когда сам выписываешь их из реального текста. Читаешь, наткнулся на незнакомое слово, посмотрел в словаре. Вечером экспортнул историю словаря в карточки и повторил.

                              0
                              Для меня идеальным приложением для изучения слов стало Vocab trainer.
                              Есть возможность импортировать слова в базу из xls
                                0
                                Функционал описанный топикстартером уже реализован в приложении Remember itunes.apple.com/app/apple-store/id1165996492?pt=118170146&ct=habra&mt=8

                                Перевод с любого из 23 языков на любой без ограничений, отличный алгоритм запоминания, абсолютно бесплатно и с отличным дизайном. Нужно было вам им писать, приложения для Android у них нет.

                                Only users with full accounts can post comments. Log in, please.