... a raczej coś zamiast.
Wierzę w metodę SuperMemo, stary DOSowy program pomógł mi trochę w czasach studenckich i mam ochotę do utrwalania wiedzy w ten sposób wrócić. Niestety bardzo nie podoba mi się aktualna inkarnacja tej aplikacji (a także kilka poprzednich).
Parę dni temu przypomniałem sobie o SuperMemo po raz kolejny, po raz kolejny mi się nie udało go skutecznie uruchomić pod Linuksem i pomyślałem o alternatywach.
W tym artykule:
- krótkie przypomnienie, o co chodzi w SuperMemo,
- namiary na programy, które mogą je zastąpić (testowane pod Linuksem, ale działają także pod Windows),
- opis, jak zdołałem wyeksportować sobie Advanced English Speed Up! oraz Advanced English Proficiency zachowując użycie plików dźwiękowych (podejście może się nadać także dla innych baz SuperMemo).
Uwaga: ostatni krok wymaga posiadania tych (lub innych) baz. Ja swoje kupiłem.
Co to jest SuperMemo
W SuperMemo chodzi o trwałe przyswajanie wiedzy. Piszemy (lub kupujemy) bazy danych w formie pytanie-odpowiedź, a program pomaga nam trwale przyswoić te informacje.
Kluczowa idea: program sam wyznacza terminy powtórek, próbując dobrać je tak, by spytać o daną rzecz ponownie wtedy, gdy będzie ona na progu bycia zapomnianą (sposób liczenia odpowiedniej daty to materia pracy doktorskiej Piotra Woźniaka, autora SuperMemo).
Szczególnie popularne zastosowanie to nauka słówek i zwrotów obcojęzycznych ale SuperMemo nadaje się do wszelkich zastosowań, w których przyswajaną wiedzę da się zapisać jako sekwencje krótkich pytań i odpowiedzi.
Popularyzatorski opis SuperMemo można znaleźć na polskiej stronie, a dokładny - włącznie z szczegółami matematycznymi - na anglojęzycznym serwisie.
Tyle o SuperMemo - metodzie. SuperMemo - program - sprzedawany był i jest na różne sposoby. W Polsce jest oferowany głównie w pakiecie z różnymi kursami (kupując właściwie cokolwiek z supermemo.pl dostajemy w komplecie program SuperMemo, ja posiadam kupione jakiś czas temu Advanced English Speed Up! oraz AdvancedEnglish Proficiency, oba zawierają SuperMemo7).
Niestety, program SuperMemo jest ... bardzo taki sobie - w sensie użytkowym. Interfejs jest nieporęczny i nieintuicyjny, często trafiają się różne błędy (nawet szokujące - ot, przy poprzedniej próbie używania - pod Windows - dostałem krzaczki zamiast polskich znaków), całość jest zwyczajnie ciężka. A szczególnie źle wyglądają próby używania SuperMemo pod Linuksem (przy pomocy Wine) - to nie działa w ogóle, to działa ale nie odtwarza dźwięku, to działa ale często się zawiesza.
Stare, DOSowe SuperMemo z lat 90-ych było bardzo fajną, ergonomiczną aplikacją (do dziś da się ją - jako freeware - znaleźć). Niestety, nie miało obsługi dźwięku.
Alternatywy dla SuperMemo
Wiem o trzech poważnych alternatywach dla SuperMemo, tj. programach używających algorytmu harmonogramowania powtórzeń pochodzącego od metody SuperMemo. Dwa są darmowe i open-source:
Oba są napisane w Pythonie, oba działają tak pod Linuksem, jak pod Windows.
Trzeci program także jest przenośny ale komercyjny:
Nie będę teraz pisał recenzji, by naprawdę ocenić taką aplikację, trzeba jej poużywać przez kilka miesięcy. Na razie wybrałem sobie do wypróbowania Mnemosyne (trochę starsze i według potocznej opinii lżejsze od Anki).
Instalacja
Obie te aplikacje są spakietowane pod Ubuntu:
$ sudo apt-get install anki mnemosyne
Dla Mnemosyne jest także dostępna nieco nowsza wersja na
stronie autora, ją instalujemy ściągając i rozpakowując
plik tar.gz
a następnie wykonując:
$ sudo python setup.py install
Tak Mnemosyne jak Anki mają również instalatory dla wersji Windows (nie testowałem).
Przy pierwszym uruchomieniu mnemosyne
tworzy
katalog ~/.mnemosyne
- miejsce na dane konfiguracyjne, a także
domyślne miejsce na bazy.
Dopisek: polska translacja Mnemosyne ma aktualnie błędy (nie działa kilka ważnych skrótów klawiszowych z spacją pokazującą odpowiedź na czele). Do czasu poprawienia problemu lepiej używać programu po angielsku (tj. z
LANG=en_US.UTF-8
lub podobnym).
Z SuperMemo do Mnemosyne
Skoro mam SpeedUp! i Proficiency, żal byłoby nie skorzystać. Dlatego postanowiłem skonwertować sobie te bazy do Mnemosyne (ponieważ Anki umie importować bazy Mnemosyne, moja technika może zostać przedłużona i w tym kierunku - ale nie testowałem tej ścieżki).
Rzecz wydawała się prosta, bo wśród opcji importu Mnemosyne
jest SuperMemo7 text in Q:/A: format
(a moje SuperMemo miało odpowiednią
opcję eksportową - Export Q&A Text
). Niestety: jak się okazało,
nie da się użyć tej metody chcąc zachować pliki dźwiękowe.
SuperMemo co prawda zadało pytanie
Export with data files?
ale po odpowiedziYes
umieściło przy każdym elemencie wzmiankę o tylko jednym z dwóch (pytanie i odpowiedź) plików dźwiękowych. Do tego importer Mnemosyne nie obsługiwał odpowiedniego zapisu (S: ścieżka
), choć to akurat było dość łatwe do poprawienia (zrobiłem szybki patch) lub obejścia (obejście: zamienićS: ścieżka
naA: <sound src="ścieżka">
w pliku eksportu).
Ostatecznie napisałem konwerter z pełnego tekstowego eksportu SuperMemo do plików XML Mnemosyne, co wraz z konwersją formatu plików dźwiękowych pozwoliło mi udanie zaimportować obie bazy do Mnemosyne.
Eksport z SuperMemo
Aby z SuperMemo eksportować, musiałem je na początek zainstalować (tj. zainstalować SpeedUp oraz Proficiency). Wine poradziło sobie z tym zadaniem poprawnie - acz same programy zawieszały się przy odgrywaniu pierwszego dźwięku.
Ten kłopot a także kłopot z naciśnięciem Ctrl-Alt-F12 (potrzebnego by przejść
w tryb pełny, w którym są dostępne opcje eksportowania) rozwiązałem
edytując ręcznie pliki ks.ini
(odpowiednio: *katalog instalacji SpeedUp*/Systems/SpeedUp!/ks.ini
oraz
*katalog instalacji Proficiency*/Systems/Proficiency/ks.ini
). W obu wypadkach
chodziło o:
- ustawienie
Mode=2
orazLevel=2
w sekcjiAccess
(ta kombinacja oznacza tryb pełny), - zakomentowanie
Sound Mode=1
w sekcjiLearning
(wyłączenie problematycznego dźwięku).
Następnie dla każdej z baz uruchomiłem SuperMemo i wybrałem
File/Export/As Text
. Powstał duży plik zaczynający się tak:
Begin Element #1
Source=Y:\SuperMemo\AdvEngSpeedUp\systems\SPEEDUP!
Parent=0
ParentTitle=
Begin ElementInfo #1
Title=Speed Up!
Type=Topic
Status=Dismissed
FirstGrade=6
Ordinal=0.000000
Repetitions=0
Lapses=0
Interval=0
LastRepetition=0
AFactor=3.000
UFactor=0.000
RepetitionHistory=0
ForgettingIndex=10
End ElementInfo #1
ElementColor=16777215
AutoPlay=1
BackgroundImage=AESUFirst.gif
...
Krótkie zamrożenie się komputera na koniec to efekt uruchomienia przez SuperMemo notatnika w celu otwarcia powyższego pliku. Przeczekałem i zamknąłem notatnik.
Skopiowanie i konwersja dźwięku i obrazków
Zamontowałem drugi CD-ROM SpeedUp i skopiowałem całą zawartość
katalogu elements
znajdującego się na nim do
Systems/SpeedUp!/elements
(w katalogu instalacji SpeedUp) - tak, by
połączyć zawartość. Uwaga: to jest mnóstwo małych plików, trwa długo.
Katalog elements
zawiera dźwięki oraz ilustracje.
Ta sama technika - skopiowanie
elements
z CD - jest przydatna także przy używaniu normalnego SuperMemo, pozwala pozbyć się konieczności ciągłego noszenia płytki. W tym wypadku trzeba także zakomentowaćSecondary
w sekcjiStorage
plikuks.ini
.
Ponieważ Mnemosyne (a raczej biblioteka pygame
) nie obsługuje
zakodowanych MP3 plików .wav
(jakich używa program), musiałem je
skonwertować. Pojedynczy plik udanie konwertuje:
$ sox -t mp3 plik.wav plik.ogg
całe drzewo obsłużyłem następującym skrypcikiem:
#!/usr/bin/perl -w
use strict;
use File::Find;
find( sub {
if ($_ =~ /^(.*)\.wav$/i) {
my $output = lc($1) . ".ogg";
unless( -f $output ) {
my $cmd = "sox -t mp3 $_ $output";
print "($File::Find::dir) $cmd\n";
system($cmd) and die $!;
}
}
}, ".");
uruchamiając go z katalogu elements
:
$ cd ścieżka/do/elements
$ perl ścieżka/do/skrypt.pl
Skrypcik na jednym z plików się
wysypał (okazał się być zwykłym .wav
), dla tego pliku ręcznie
zrobiłem:
$ sox plik.wav plik.ogg
i uruchomiłem całość ponownie (skrypcik nie powtarza konwersji już skonwertowanych plików).
Uwaga: ta konwersja trwała kilka godzin.
Jeśli nie będziemy już używać orginalnego SuperMemo, można na koniec oszczędzić miejsca i usunąć pliki
.wav
:$ cd ścieżka/do/elements $ find . -name '*.wav' -exec rm {} \; $ find . -name '*.WAV' -exec rm {} \;
Całą powyższą operację powtórzyłem też dla Proficiency.
Na koniec podsymlinkowałem sobie te katalogi w katalogu ~/.mnemosyne
:
$ mkdir ~/.mnemosyne/SuperMemo
$ ln -s /ścieżka/do/SpeedUp/elements \
~/.mnemosyne/SuperMemo/SpeedUpElements
$ ln -s /ścieżka/do/Proficiency/elements \
~/.mnemosyne/SuperMemo/ProficiencyElements
Konwersja eksportu SuperMemo do pliku importowego Mnemosyne
Napisałem niezbyt długi skrypt pythonowy konwertujący stworzony
wyżej eksport .txt
do formatu XML Mnemosyne. Mój skrypt przy okazji poprawiał ścieżki
do plików graficznych i dźwiękowych.
Skrypt jest tutaj: smexport_to_mnemosyne_xml.py
Uwaga: smexport_to_mnemosyne_xml.py nie kopiuje danych o wynikach nauczania (moje stare wyniki nie były warte zachowania). To można dorobić i nawet chyba nie byłoby to bardzo trudne, patrz
# TODO: copy learning data...
w treści skryptu.
W celu użycia skryptu należy napisać króciutki plik konfiguracyjny, np. taki:
CONVERT = dict(
input_file = "/home/mekk/SpeedUpExport.txt",
output_file = "/home/mekk/SpeedUpExport.xml",
name_mapper = FileNameMapper(
orig_root = 'Y:\AdvEngSpeedUp\systems\SPEEDUP!\elements',
dest_root = "SuperMemo/SpeedUpElements",
convert_slashes = True,
convert_ext = { 'wav' : 'ogg' }),
category_mapper = CategoryMapper(
re.compile('^(Speed Up!|Advanced English|\[\d.*|\#\d.*)$')),
)
Znaczenie opcji:
input_file
to miejsce, gdzie jest zapisany tekstowy eksport z SuperMemo,output_file
to tworzony plik.xml
Mnemosyne,name_mapper
to funkcja zamieniająca orginalne nazwy plików na docelowe (patrz niżej),category_mapper
to funkcja generująca nazwy kategorii (także patrz niżej).
Funkcję name_mapper
można napisać samemu (w pythonie, powyższe to
kod pythonowy). Dostaje jako parametr rzeczy takie jak
Y:\SuperMemo\AdvEngSpeedUp\systems\SPEEDUP!\elements\1\11\11.wav
,
powinna zwrócić linuksową ścieżkę do odpowiedniego pliku. Gotowiec
FileNameMapper
obsługuje typową sytuację:
-
zamienia prefiks
orig_root
(trzeba poprawić według tego, co powstało w tekstowym eksporcie z SuperMemo) nadest_root
(może być to ścieżka pełna albo względna w stosunku do~/.mnemosyne
, powyższy przykład stosuje tę drugą konwencję zgodnie z symlinkami, które zrobiłem po konwersji), -
zamienia
\
na '/' w pozostałej części ścieżki (bo jest ustawioneconvert_slashes
, przy próbach użycia skryptu na Windows tej opcji bym nie ustawiał), -
zamienia rozszerzenia
.wav
na.ogg
.
Funkcję category_mapper
także można napisać samemu. Dostaje ona jako
parametry ścieżkę tematów z bazy SuperMemo (np. może zostać
zawołana jako funkcja_map('Speed Up!', 'Advanced English', 'General English', 'Body Life and Living Creatures', 'Head and the Face', '#1 Head and the Face')
,
zwraca zaś pojedynczy napis, tj. nazwę kategorii Mnemosyne. Gotowiec
CategoryMapper
pomija elementy opisane przez wyrażenie regularne
zadane jako parametr konstruktora, w pozostałych zamienia spacje i nielegalne
znaki na podkreślenia i łączy je myślnikami. Dla powyższego
parametru stworzy General_English-Body_Life_and_Living_Creatures-Head_and_the_Face
.
Przykładowe wyrażenie pomija dwa nagłówki najwyższego poziomu, a także
końcowe (trafiające się w formie #3 Food
ale też [2] Math
).
Nazwy kategorii Mnemosyne muszą być poprawnymi nazwami tagów XML, tj. składać się wyłącznie z liter, cyfr, myślników i podkreślników.
Po napisaniu powyższego pliku (zapisanego np. jako speedup.cfg
),
można uruchomić skrypt:
$ python smexport_to_mnemosyne_xml.py speedup.cfg
działanie potrwa kilka-kilkanaście minut (i zajmie sporo pamięci). Na bieżąco będą się pojawiać informacje o konwertowanych kategoriach.
Konwersję Proficiency
robiłem analogicznie, poprawiłem
jedynie ścieżki i zmieniłem w wyrażeniu regularnym pomijanych
kategorii SpeedUp!
na Proficiency
.
Właściwy import do Mnemosyne
Czas na właściwy import do Mnemosyne. W tym celu:
-
tworzymy lub otwieramy bazę Mnemosyne, do której chcemy importować (kwestia osobistych preferencji - czy wkładać to do domyślnej, czy zrobić dedykowaną, ja ostatecznie zaimportowałem oba kursy do bazy domyślnej),
-
wybieramy
Plik/Importuj
-
ustawiamy format
XML
, wybieramy plik stworzony w wcześniejszym kroku, kategorię wpisujemy dowolnie (nie powinno być to potrzebne, eksport ma poustawiane kategorie) -
klikamy OK (uwaga niedoróbka: naciśnięcie Enter zamyka okno nic nie robiąc)
Przycisk OK powinien się wcisnąć, co oznacza trwanie importu (program niestety nie ma żadnego progress-baru). Zamknięcie okna i pojawienie się pierwszego pytania oznacza sukces. W trakcie importu można sobie zrobić
$ tail -f ~/.mnemosyne/log.txt
(tu też zaczyna się cokolwiek dziać po jednej czy paru minutach, wcześniej trwa parsowanie XML).
Łącznie import trwa około 10 minut (na moim słabym komputerze).
Jeśli pojawi się okienko błędu zawierające coś takiego:
Błąd składni XML:
...
...
SAXParseException: <unknown>:128170:62: not well-formed (invalid token)
trzeba otworzyć plik XML w edytorze, znaleźć odpowiedni wiersz i kolumnę (tu: wiersz 128170 kolumna 62) i poprawić kłopotliwy znak. Starałem się wyczyścić zauważone śmieci ale są różnorodne.
Patrz procedura
escape_xml
w skrypcie, oczywiście można ją uzupełnić i powtórzyć konwersję.
Test
Przechodzimy przez kilka pytań. Jeśli teksty się pojawiają, a pliki dźwiękowe odgrywają - osiągnęliśmy sukces.