На данный момент создано множество приложений для запоминания слов. Из тех что мне запомнились могу выделить такие 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 для получения перевода, транскрипции и звукового воспроизведения. Для работы приложения необходим доступ в интернет.

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

Комментарии (25)


  1. vladshow Автор
    09.08.2017 00:33

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

    Также доступна web версия приложения по адресу:
    https://svlaboratory.org/application/english-words


    1. m0Ray
      09.08.2017 09:48

      1) На svlaboratory.org проблемы с HTTPS — просрочен сертификат.
      2) Как быть, если хочется поучить слова, скажем, узбекского языка?


      1. r4nd0m
        09.08.2017 10:40

        2) Как быть, если хочется поучить слова, скажем, узбекского языка?

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


        1. m0Ray
          09.08.2017 10:56

          И что-то не наблюдаю там готовых решений для узбекского языка. У топикстартера хоть можно по-быстрому из словаря надёргать.


          1. r4nd0m
            09.08.2017 11:15

            Надёргать и импортировать (например, отсюда) можно везде, но у автора главный недостаток — платный акаунт. Решать его написанием приложения, при существующем anki, решение довольно спорное. Уж поверьте мне, я сам когда-то таким занимался, но исключительно из за того, что на нужной мне платформе не было anki.


      1. vladshow Автор
        09.08.2017 14:09

        1) Используйте HTTP:
        http://svlaboratory.org/application/english-words
        2) В интерфейсе приложения приведены возможные направления переводов:
        ru, en, pl, uk, de, fr, es, it, tr.
        К сожалению Yandex API не предоставляет возможность переводов для узбекского языка.


      1. web_dev
        10.08.2017 10:29

        Здравствуйте, попробуйте это приложение, старался создать универсальное приложение для изучения слов любого иностарнного языка. Различного функционала и настроек очень много. Полностью бесплатное. https://play.google.com/store/apps/details?id=com.jdev.tutor


    1. John_SC
      09.08.2017 14:12

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


      1. vladshow Автор
        09.08.2017 14:16

  1. aamonster
    09.08.2017 00:45
    +2

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


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


    1. web_dev
      10.08.2017 10:31

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


      1. aamonster
        10.08.2017 15:18

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


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


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


  1. Simipa
    09.08.2017 09:18

    Хм, идея хорошая, но реализация подкачала. Я уже некоторое время думаю над своим решением, и концепцию офлайна я уже придумал. Ваша же статья привела меня к несколько другой мысли. В общем, пойду работать дальше, возможно, довольно скоро, приведу свой вариант)


  1. bro-dev
    09.08.2017 09:57
    +6

    Заголовок вводит в заблуждение, когда я читаю «Алгоритм для запоминания» я жду что будет что то связанное с тем как запоминать в голове, а не на компьютер.
    А главный недостаток сервисов всех что я видел, то что они скрывают статистику(скорее всего удручающую) по использованию их сервиса.


  1. dklein
    09.08.2017 10:13

    Система запоминания слов «по карточкам» неэффективна. Я даже статью писал на эту тему. Слова существуют вне контекста, а запоминаются лишь из-за частого мелькания на экране телефона и дальше, чем в кратковременную память, не попадают. Но я понял, что пост вовсе не об этом :)


    1. dadyjo
      09.08.2017 10:25
      +1

      А где статья? В Вашем профиле ее не вижу.


    1. marenkov
      09.08.2017 11:37

      Именно так. С карточками можно набрать только базовый набор слов, которые постоянно встречаешь в текстах. И именно факт их использования в реальной ситуации помогает из запомнить.

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

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


      1. wladyspb
        09.08.2017 12:42

        То есть, мы приходим к дуо лингво?)

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


        1. marenkov
          09.08.2017 12:54

          Дуо лингво хорошо, но только для начинающих. Хотелось бы видеть там более продвинутые уровни.


        1. Hardcoin
          09.08.2017 21:03

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


          1. dadyjo
            10.08.2017 10:57

            Там гораздо больше чем пара сотен.

            За 31 урок что я прошел Doulingo пишет что мой словарный запас 840 слов и уровень знания английского 22%. Впереди еще 22 урока непройденных. Думаю программа расчитана на вполне приличный соварный запас в 3-4 тысячи слов.


        1. satou1993
          10.08.2017 14:46

          Попробуйте Lingvist.


    1. Hardcoin
      09.08.2017 20:58

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


    1. aamonster
      10.08.2017 15:10

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


  1. astono0
    13.08.2017 18:16

    Для меня идеальным приложением для изучения слов стало Vocab trainer.
    Есть возможность импортировать слова в базу из xls